Merge branch 'refactor-network-string'
This commit is contained in:
@@ -593,9 +593,9 @@ namespace UserConfigParams
|
||||
"stun.voxgratia.org",
|
||||
"stun.xten.com") );
|
||||
|
||||
PARAM_PREFIX StringUserConfigParam m_packets_log_filename
|
||||
PARAM_DEFAULT( StringUserConfigParam("packets_log.txt", "packets_log_filename",
|
||||
"Where to log received and sent packets.") );
|
||||
PARAM_PREFIX BoolUserConfigParam m_log_packets
|
||||
PARAM_DEFAULT( BoolUserConfigParam(false, "log-network-packets",
|
||||
"If all network packets should be logged") );
|
||||
|
||||
// ---- Graphic Quality
|
||||
PARAM_PREFIX GroupUserConfigParam m_graphics_quality
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#ifndef HEADER_SHADERS_HPP
|
||||
#define HEADER_SHADERS_HPP
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/shader.hpp"
|
||||
#include "graphics/shared_gpu_objects.hpp"
|
||||
#include "graphics/texture_shader.hpp"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "graphics/shadow_matrices.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
|
||||
@@ -151,6 +151,9 @@ public:
|
||||
return fileExists(std::string(prefix) + path);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the name of the stdout file for log messages. */
|
||||
static const std::string& getStdoutName() { return m_stdout_filename; }
|
||||
// ------------------------------------------------------------------------
|
||||
void listFiles (std::set<std::string>& result,
|
||||
const std::string& dir,
|
||||
bool make_full_path=false) const;
|
||||
|
||||
@@ -173,6 +173,7 @@
|
||||
#include "modes/demo_world.hpp"
|
||||
#include "modes/profile_world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/servers_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "online/profile_manager.hpp"
|
||||
@@ -1666,6 +1667,7 @@ static void cleanUserConfig()
|
||||
void runUnitTests()
|
||||
{
|
||||
GraphicsRestrictions::unitTesting();
|
||||
NetworkString::unitTesting();
|
||||
// Test easter mode: in 2015 Easter is 5th of April - check with 0 days
|
||||
// before and after
|
||||
int saved_easter_mode = UserConfigParams::m_easter_ear_mode;
|
||||
@@ -1695,4 +1697,4 @@ void runUnitTests()
|
||||
assert( isEasterMode(22, 3, 2016, 5));
|
||||
assert(!isEasterMode(21, 3, 2016, 5));
|
||||
UserConfigParams::m_easter_ear_mode = saved_easter_mode;
|
||||
} // unitTesting
|
||||
} // runUnitTests
|
||||
|
||||
@@ -46,20 +46,28 @@ Event::Event(ENetEvent* event)
|
||||
}
|
||||
if (m_type == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
m_data = NetworkString(std::string((char*)(event->packet->data),
|
||||
event->packet->dataLength-1));
|
||||
m_data = new NetworkString(event->packet->data,
|
||||
event->packet->dataLength);
|
||||
}
|
||||
else
|
||||
m_data = NULL;
|
||||
|
||||
m_packet = NULL;
|
||||
if (event->packet)
|
||||
{
|
||||
m_packet = event->packet;
|
||||
// we got all we need, just remove the data.
|
||||
enet_packet_destroy(m_packet);
|
||||
enet_packet_destroy(event->packet);
|
||||
}
|
||||
m_packet = NULL;
|
||||
|
||||
m_peer = STKHost::get()->getPeer(event->peer);
|
||||
if(m_type == EVENT_TYPE_MESSAGE && m_peer->isClientServerTokenSet() &&
|
||||
m_data->getToken()!=m_peer->getClientServerToken() )
|
||||
{
|
||||
Log::error("Event", "Received event with invalid token!");
|
||||
Log::error("Event", "HostID %d Token %d message token %d",
|
||||
m_peer->getHostId(), m_peer->getClientServerToken(),
|
||||
m_data->getToken());
|
||||
Log::error("Event", m_data->getLogMessage().c_str());
|
||||
}
|
||||
} // Event(ENetEvent)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -70,15 +78,6 @@ Event::~Event()
|
||||
// Do not delete m_peer, it's a pointer to the enet data structure
|
||||
// which is persistent.
|
||||
m_peer = NULL;
|
||||
m_packet = NULL;
|
||||
delete m_data;
|
||||
} // ~Event
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** \brief Remove bytes at the beginning of data.
|
||||
* \param size : The number of bytes to remove.
|
||||
*/
|
||||
void Event::removeFront(int size)
|
||||
{
|
||||
m_data.removeFront(size);
|
||||
} // removeFront
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
#ifndef EVENT_HPP
|
||||
#define EVENT_HPP
|
||||
|
||||
#include "network/network_string.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include "enet/enet.h"
|
||||
|
||||
class NetworkString;
|
||||
class STKPeer;
|
||||
|
||||
/*!
|
||||
@@ -57,11 +57,9 @@ class Event
|
||||
{
|
||||
private:
|
||||
LEAK_CHECK()
|
||||
/** Copy of the data passed by the event. */
|
||||
NetworkString m_data;
|
||||
|
||||
/** A pointer on the ENetPacket to be deleted. */
|
||||
ENetPacket* m_packet;
|
||||
/** Copy of the data passed by the event. */
|
||||
NetworkString *m_data;
|
||||
|
||||
/** Type of the event. */
|
||||
EVENT_TYPE m_type;
|
||||
@@ -72,7 +70,6 @@ private:
|
||||
public:
|
||||
Event(ENetEvent* event);
|
||||
~Event();
|
||||
void removeFront(int size);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the type of this event. */
|
||||
@@ -85,12 +82,12 @@ public:
|
||||
/** \brief Get a const reference to the received data.
|
||||
* This is empty for events like connection or disconnections.
|
||||
*/
|
||||
const NetworkString& data() const { return m_data; }
|
||||
const NetworkString& data() const { return *m_data; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** \brief Get a non-const reference to the received data.
|
||||
* A copy of the message data. This is empty for events like
|
||||
* connection or disconnections. */
|
||||
NetworkString& data() { return m_data; }
|
||||
NetworkString& data() { return *m_data; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
}; // class Event
|
||||
|
||||
@@ -82,10 +82,9 @@ ENetPeer *Network::connectTo(const TransportAddress &address)
|
||||
/** \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 Network::sendRawPacket(uint8_t* data, int length,
|
||||
void Network::sendRawPacket(const BareNetworkString &buffer,
|
||||
const TransportAddress& dst)
|
||||
{
|
||||
struct sockaddr_in to;
|
||||
@@ -96,11 +95,11 @@ void Network::sendRawPacket(uint8_t* data, int length,
|
||||
to.sin_port = htons(dst.getPort());
|
||||
to.sin_addr.s_addr = htonl(dst.getIP());
|
||||
|
||||
sendto(m_host->socket, (char*)data, length, 0,(sockaddr*)&to, to_len);
|
||||
sendto(m_host->socket, buffer.getData(), buffer.size(), 0,
|
||||
(sockaddr*)&to, to_len);
|
||||
Log::verbose("Network", "Raw packet sent to %s",
|
||||
dst.toString().c_str());
|
||||
Network::logPacket(NetworkString(std::string((char*)(data), length)),
|
||||
false);
|
||||
Network::logPacket(buffer, false);
|
||||
} // sendRawPacket
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -146,7 +145,7 @@ int Network::receiveRawPacket(char *buffer, int buf_len,
|
||||
if(len<0)
|
||||
return -1;
|
||||
|
||||
Network::logPacket(NetworkString(std::string(buffer, len)), true);
|
||||
Network::logPacket(BareNetworkString(buffer, len), true);
|
||||
sender->setIP(ntohl((uint32_t)(addr.sin_addr.s_addr)) );
|
||||
sender->setPort( ntohs(addr.sin_port) );
|
||||
if (addr.sin_family == AF_INET)
|
||||
@@ -161,9 +160,9 @@ int Network::receiveRawPacket(char *buffer, int buf_len,
|
||||
/** \brief Broadcasts a packet to all peers.
|
||||
* \param data : Data to send.
|
||||
*/
|
||||
void Network::broadcastPacket(const NetworkString& data, bool reliable)
|
||||
void Network::broadcastPacket(NetworkString *data, bool reliable)
|
||||
{
|
||||
ENetPacket* packet = enet_packet_create(data.getBytes(), data.size() + 1,
|
||||
ENetPacket* packet = enet_packet_create(data->getData(), data->size() + 1,
|
||||
reliable ? ENET_PACKET_FLAG_RELIABLE
|
||||
: ENET_PACKET_FLAG_UNSEQUENCED);
|
||||
enet_host_broadcast(m_host, 0, packet);
|
||||
@@ -173,10 +172,10 @@ void Network::broadcastPacket(const NetworkString& data, bool reliable)
|
||||
void Network::openLog()
|
||||
{
|
||||
m_log_file.setAtomic(NULL);
|
||||
if (UserConfigParams::m_packets_log_filename.toString() != "")
|
||||
if (UserConfigParams::m_log_packets)
|
||||
{
|
||||
std::string s = file_manager
|
||||
->getUserConfigFile(UserConfigParams::m_packets_log_filename);
|
||||
->getUserConfigFile(FileManager::getStdoutName()+".packet");
|
||||
m_log_file.setAtomic(fopen(s.c_str(), "w+"));
|
||||
}
|
||||
if (!m_log_file.getData())
|
||||
@@ -189,7 +188,7 @@ void Network::openLog()
|
||||
* \param incoming : True if the packet comes from a peer.
|
||||
* False if it's sent to a peer.
|
||||
*/
|
||||
void Network::logPacket(const NetworkString &ns, bool incoming)
|
||||
void Network::logPacket(const BareNetworkString &ns, bool incoming)
|
||||
{
|
||||
if (m_log_file.getData() == NULL) // read only access, no need to lock
|
||||
return;
|
||||
@@ -199,12 +198,10 @@ void Network::logPacket(const NetworkString &ns, bool incoming)
|
||||
m_log_file.lock();
|
||||
fprintf(m_log_file.getData(), "[%d\t] %s ",
|
||||
(int)(StkTime::getRealTime()), arrow);
|
||||
|
||||
for (int i = 0; i < ns.size(); i++)
|
||||
{
|
||||
fprintf(m_log_file.getData(), "%d.", ns[i]);
|
||||
}
|
||||
fprintf(m_log_file.getData(), "\n");
|
||||
// Indentation for all lines after the first, so that the dump
|
||||
// is nicely aligned.
|
||||
std::string indent(" ");
|
||||
fprintf(m_log_file.getData(), "%s", ns.getLogMessage(indent).c_str());
|
||||
m_log_file.unlock();
|
||||
} // logPacket
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class BareNetworkString;
|
||||
class NetworkString;
|
||||
class TransportAddress;
|
||||
|
||||
@@ -57,14 +58,14 @@ public:
|
||||
virtual ~Network();
|
||||
|
||||
static void openLog();
|
||||
static void logPacket(const NetworkString &ns, bool incoming);
|
||||
static void logPacket(const BareNetworkString &ns, bool incoming);
|
||||
static void closeLog();
|
||||
ENetPeer *connectTo(const TransportAddress &address);
|
||||
void sendRawPacket(uint8_t* data, int length,
|
||||
void sendRawPacket(const BareNetworkString &buffer,
|
||||
const TransportAddress& dst);
|
||||
int receiveRawPacket(char *buffer, int buf_len,
|
||||
TransportAddress* sender, int max_tries = -1);
|
||||
void broadcastPacket(const NetworkString& data,
|
||||
void broadcastPacket(NetworkString *data,
|
||||
bool reliable = true);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a pointer to the ENet host object. */
|
||||
|
||||
@@ -171,9 +171,3 @@ void NetworkConsole::kickAllPlayers()
|
||||
peers[i]->disconnect();
|
||||
}
|
||||
} // kickAllPlayers
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void NetworkConsole::sendPacket(const NetworkString& data, bool reliable)
|
||||
{
|
||||
m_localhost->broadcastPacket(data, reliable);
|
||||
} // sendPacket
|
||||
|
||||
@@ -43,14 +43,12 @@ public:
|
||||
virtual ~NetworkConsole();
|
||||
|
||||
virtual void run();
|
||||
|
||||
void setMaxPlayers(uint8_t count) { m_max_players = count; }
|
||||
uint8_t getMaxPlayers() { return m_max_players; }
|
||||
|
||||
void kickAllPlayers();
|
||||
|
||||
virtual void sendPacket(const NetworkString& data, bool reliable = true);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void setMaxPlayers(uint8_t count) { m_max_players = count; }
|
||||
// ------------------------------------------------------------------------
|
||||
uint8_t getMaxPlayers() { return m_max_players; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual bool isServer() { return true; }
|
||||
|
||||
}; // class NetworkConsole
|
||||
|
||||
@@ -14,33 +14,78 @@
|
||||
// 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_string.hpp"
|
||||
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
NetworkString operator+(NetworkString const& a, NetworkString const& b)
|
||||
#include <algorithm> // for std::min
|
||||
#include <iomanip>
|
||||
#include <ostream>
|
||||
|
||||
// ============================================================================
|
||||
/** Unit testing function.
|
||||
*/
|
||||
void NetworkString::unitTesting()
|
||||
{
|
||||
NetworkString ns(a);
|
||||
ns += b;
|
||||
return ns;
|
||||
} // operator+
|
||||
NetworkString s(PROTOCOL_LOBBY_ROOM);
|
||||
assert(s.getProtocolType() == PROTOCOL_LOBBY_ROOM);
|
||||
assert(s.getProtocolType() != PROTOCOL_KART_UPDATE);
|
||||
assert(!s.isSynchronous());
|
||||
s.setSynchronous(true);
|
||||
assert(s.isSynchronous());
|
||||
s.setSynchronous(false);
|
||||
assert(!s.isSynchronous());
|
||||
|
||||
uint32_t token = 0x12345678;
|
||||
// Check token setting and reading
|
||||
s.setToken(token);
|
||||
assert(s.getToken()==token);
|
||||
assert(s.getToken()!=0x87654321);
|
||||
|
||||
// Append some values from the message
|
||||
s.addUInt16(12345);
|
||||
s.addFloat(1.2345f);
|
||||
// Ignore message type and token
|
||||
s.removeFront(5);
|
||||
|
||||
assert(s.getUInt16(0) == 12345);
|
||||
float f = s.getFloat(2);
|
||||
assert(f==1.2345f);
|
||||
|
||||
// Check modifying a token in an already assembled message
|
||||
uint32_t new_token = 0x87654321;
|
||||
s.setToken(new_token);
|
||||
assert(s.getToken()!=token);
|
||||
assert(s.getToken()==new_token);
|
||||
|
||||
// Check log message format
|
||||
BareNetworkString slog(28);
|
||||
for(unsigned int i=0; i<28; i++)
|
||||
slog.addUInt8(i);
|
||||
std::string log = slog.getLogMessage();
|
||||
assert(log=="0x000 | 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f | ................\n"
|
||||
"0x010 | 10 11 12 13 14 15 16 17 18 19 1a 1b | ............\n");
|
||||
} // unitTesting
|
||||
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Adds one byte for the length of the string, and then (up to 255 of)
|
||||
* the characters of the given string. */
|
||||
NetworkString& NetworkString::encodeString(const std::string &value)
|
||||
* the characters of the given string. */
|
||||
BareNetworkString& BareNetworkString::encodeString(const std::string &value)
|
||||
{
|
||||
int len = value.size();
|
||||
if(len<=255)
|
||||
return addUInt8(len).addString(value);
|
||||
return this->addUInt8(len).addString(value);
|
||||
else
|
||||
return addUInt8(255).addString(value.substr(0, 255));
|
||||
} // encodeString
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Adds one byte for the length of the string, and then (up to 255 of)
|
||||
/** Adds one byte for the length of the string, and then (up to 255 of)
|
||||
* the characters of the given string. */
|
||||
NetworkString& NetworkString::encodeString(const irr::core::stringw &value)
|
||||
BareNetworkString& BareNetworkString::encodeString(const irr::core::stringw &value)
|
||||
{
|
||||
std::string v = StringUtils::wideToUtf8(value);
|
||||
return encodeString(v);
|
||||
@@ -53,9 +98,9 @@ NetworkString& NetworkString::encodeString(const irr::core::stringw &value)
|
||||
* \param[out] out The decoded string.
|
||||
* \return number of bytes read = 1+length of string
|
||||
*/
|
||||
int NetworkString::decodeString(int pos, std::string *out) const
|
||||
int BareNetworkString::decodeString(int pos, std::string *out) const
|
||||
{
|
||||
uint8_t len = getUInt8(pos);
|
||||
uint8_t len = get<uint8_t>(m_current_offset+pos);
|
||||
*out = getString(pos+1, len);
|
||||
return len+1;
|
||||
} // decodeString
|
||||
@@ -70,10 +115,59 @@ int NetworkString::decodeString(int pos, std::string *out) const
|
||||
* characters can mean that the length of the returned string is
|
||||
* less than the number of bytes read.
|
||||
*/
|
||||
int NetworkString::decodeStringW(int pos, irr::core::stringw *out) const
|
||||
int BareNetworkString::decodeStringW(int pos, irr::core::stringw *out) const
|
||||
{
|
||||
std::string s;
|
||||
int len = decodeString(pos, &s);
|
||||
*out = StringUtils::utf8ToWide(s);
|
||||
return len;
|
||||
} // decodeString
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns a string representing this message suitable to be printed
|
||||
* to stdout or via the Log mechanism. Format
|
||||
* 0000 : 1234 5678 9abc ... ASCII-
|
||||
*/
|
||||
std::string BareNetworkString::getLogMessage(const std::string &indent) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
for(unsigned int line=0; line<m_buffer.size(); line+=16)
|
||||
{
|
||||
oss << "0x" << std::hex << std::setw(3) << std::setfill('0')
|
||||
<< line << " | ";
|
||||
unsigned int upper_limit = std::min(line+16, (unsigned int)m_buffer.size());
|
||||
for(unsigned int i=line; i<upper_limit; i++)
|
||||
{
|
||||
oss << std::hex << std::setfill('0') << std::setw(2)
|
||||
<< int(m_buffer[i])<< ' ';
|
||||
if(i%8==7) oss << " ";
|
||||
} // for i
|
||||
// fill with spaces if necessary to properly align ascii columns
|
||||
for(unsigned int i=upper_limit; i<line+16; i++)
|
||||
{
|
||||
oss << " ";
|
||||
if (i%8==7) oss << " ";
|
||||
}
|
||||
|
||||
// Add ascii representation
|
||||
oss << " | ";
|
||||
for(unsigned int i=line; i<upper_limit; i++)
|
||||
{
|
||||
uint8_t c = m_buffer[i];
|
||||
// Don't print tabs, and characters >=128, which are often shown
|
||||
// as more than one character.
|
||||
if(isprint(c) && c!=0x09 && c<=0x80)
|
||||
oss << char(c);
|
||||
else
|
||||
oss << '.';
|
||||
} // for i
|
||||
oss << "\n";
|
||||
// If it's not the last line, add the indentation in front
|
||||
// of the next line
|
||||
if(line+16<m_buffer.size())
|
||||
oss << indent;
|
||||
} // for line
|
||||
|
||||
return oss.str();
|
||||
} // getLogMessage
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#ifndef NETWORK_STRING_HPP
|
||||
#define NETWORK_STRING_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/types.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
@@ -38,289 +40,205 @@
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
/** \class NetworkString
|
||||
/** \class BareNetworkString
|
||||
* \brief Describes a chain of 8-bit unsigned integers.
|
||||
* This class allows you to easily create and parse 8-bit strings.
|
||||
* This class allows you to easily create and parse 8-bit strings, has
|
||||
* functions to add and read other data types (e.g. int, strings). It does
|
||||
* not enforce any structure on the sequence (NetworkString uses this as
|
||||
* a base class, and enforces a protocol type in the first byte, and a
|
||||
* 4-byte authentication token in bytes 2-5)
|
||||
*/
|
||||
class NetworkString
|
||||
|
||||
class BareNetworkString
|
||||
{
|
||||
private:
|
||||
union FloatAsInt
|
||||
{
|
||||
float f;
|
||||
uint8_t i[4];
|
||||
}; // float as integer
|
||||
LEAK_CHECK();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
union {
|
||||
double d;
|
||||
uint8_t i[8];
|
||||
} d_as_i; // double as integer
|
||||
protected:
|
||||
/** The actual buffer. */
|
||||
std::vector<uint8_t> m_buffer;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
std::vector<uint8_t> m_string;
|
||||
/** To avoid copying the buffer when bytes are deleted (which only
|
||||
* happens at the front), use an offset index. All positions given
|
||||
* by the user will be relative to this index. Note that the type
|
||||
* should be left as signed, otherwise certain arithmetic (e.g.
|
||||
* 1-m_current_offset in checkToken() will be done unsigned).
|
||||
*/
|
||||
int m_current_offset;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a part of the network string as a std::string. This is an
|
||||
* internal function only, the user should call decodeString(W) instead.
|
||||
* \param pos First position to be in the string.
|
||||
* \param len Number of bytes to copy.
|
||||
*/
|
||||
* internal function only, the user should call decodeString(W) instead.
|
||||
* \param pos First position to be in the string.
|
||||
* \param len Number of bytes to copy.
|
||||
*/
|
||||
std::string getString(int pos, int len) const
|
||||
{
|
||||
return std::string(m_string.begin() + pos,
|
||||
m_string.begin() + pos + len);
|
||||
return std::string(m_buffer.begin() + (m_current_offset+pos ),
|
||||
m_buffer.begin() + (m_current_offset+pos + len) );
|
||||
} // getString
|
||||
|
||||
public:
|
||||
/** Dummy constructor. */
|
||||
NetworkString() { }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Constructor to store one byte. */
|
||||
NetworkString(int len)
|
||||
{
|
||||
m_string.reserve(len);
|
||||
} // NetworkString(int)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Copy constructor. */
|
||||
NetworkString(NetworkString const& copy) { m_string = copy.m_string; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Copy the data from a string. */
|
||||
NetworkString(const std::string & value)
|
||||
{
|
||||
m_string = std::vector<uint8_t>(value.begin(), value.end());
|
||||
} // NetworkString
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
NetworkString(const char *p, int len)
|
||||
{
|
||||
m_string.resize(len);
|
||||
memcpy(m_string.data(), p, len);
|
||||
} // NetworkString(char*, int)
|
||||
// ------------------------------------------------------------------------
|
||||
NetworkString& encodeString(const std::string &value);
|
||||
NetworkString& encodeString(const irr::core::stringw &value);
|
||||
int decodeString(int n, std::string *out) const;
|
||||
int decodeStringW(int n, irr::core::stringw *out) const;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
NetworkString& removeFront(int size)
|
||||
{
|
||||
m_string.erase(m_string.begin(), m_string.begin() + size);
|
||||
return *this;
|
||||
} // removeFront
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
NetworkString& remove(int pos, int size)
|
||||
{
|
||||
m_string.erase(m_string.begin() + pos, m_string.begin() + pos + size);
|
||||
return *this;
|
||||
} // remove
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
uint8_t operator[](const int& pos) const
|
||||
{
|
||||
return getUInt8(pos);
|
||||
} // operator[]
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Add 8 bit unsigned int. */
|
||||
NetworkString& addUInt8(const uint8_t& value)
|
||||
{
|
||||
m_string.push_back(value);
|
||||
return *this;
|
||||
} // addUInt8
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds 8 bit integer. */
|
||||
inline NetworkString& ai8(const uint8_t& value) { return addUInt8(value); }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds 16 bit unsigned int. */
|
||||
NetworkString& addUInt16(const uint16_t& value)
|
||||
{
|
||||
m_string.push_back((value >> 8) & 0xff);
|
||||
m_string.push_back(value & 0xff);
|
||||
return *this;
|
||||
} // addUInt16
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds 16 bit integer. */
|
||||
inline NetworkString& ai16(const uint16_t& value)
|
||||
{
|
||||
return addUInt16(value);
|
||||
} // ai16
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds unsigned 32 bit integer. */
|
||||
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;
|
||||
} // addUInt32
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds 32 bit integer. */
|
||||
inline NetworkString& ai32(const uint32_t& value)
|
||||
{
|
||||
return addUInt32(value);
|
||||
} // ai32
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
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;
|
||||
} // addInt
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
inline NetworkString& ai(const int& value) { return addInt(value); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a 4 byte floating point value. */
|
||||
NetworkString& addFloat(const float& value) //!< BEWARE OF PRECISION
|
||||
{
|
||||
assert(sizeof(float) == 4);
|
||||
FloatAsInt f_as_i;
|
||||
f_as_i.f = value;
|
||||
m_string.push_back(f_as_i.i[0]);
|
||||
m_string.push_back(f_as_i.i[1]);
|
||||
m_string.push_back(f_as_i.i[2]);
|
||||
m_string.push_back(f_as_i.i[3]);
|
||||
return *this;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a 4 byte floating point value. */
|
||||
inline NetworkString& af(const float& value) { return addFloat(value); }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a 8 byte floating point 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;
|
||||
} // addDouble
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds n 8 byte floating point value. */
|
||||
inline NetworkString& ad(const double& value) { return addDouble(value); }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a single character to the string. */
|
||||
NetworkString& addChar(const char& value)
|
||||
{
|
||||
m_string.push_back((uint8_t)(value));
|
||||
return *this;
|
||||
} // addChar
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a single character. */
|
||||
inline NetworkString& ac(const char& value) { return addChar(value); }
|
||||
|
||||
/** Adds a string. */
|
||||
NetworkString& addString(const std::string& value)
|
||||
/** Adds a std::string. Internal use only. */
|
||||
BareNetworkString& addString(const std::string& value)
|
||||
{
|
||||
for (unsigned int i = 0; i < value.size(); i++)
|
||||
m_string.push_back((uint8_t)(value[i]));
|
||||
m_buffer.push_back((uint8_t)(value[i]));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a string. */
|
||||
inline NetworkString& as(const std::string& value)
|
||||
{
|
||||
return addString(value);
|
||||
} // as
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds the content of another network string. */
|
||||
NetworkString& operator+=(NetworkString const& value)
|
||||
{
|
||||
m_string.insert(m_string.end(), value.m_string.begin(),
|
||||
value.m_string.end() );
|
||||
return *this;
|
||||
} // operator+=
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds the xyz components of a Vec3 to the string. */
|
||||
NetworkString& add(const Vec3 &xyz)
|
||||
{
|
||||
return addFloat(xyz.getX()).addFloat(xyz.getY()).addFloat(xyz.getZ());
|
||||
} // add
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds the four components of a quaternion. */
|
||||
NetworkString& add(const btQuaternion &quat)
|
||||
{
|
||||
return addFloat(quat.getX()).addFloat(quat.getY())
|
||||
.addFloat(quat.getZ()).addFloat(quat.getW());
|
||||
} // add
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the content of the network string as a std::string. */
|
||||
const std::string std_string() const
|
||||
{
|
||||
std::string str(m_string.begin(), m_string.end());
|
||||
return str;
|
||||
} // std_string
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current length of the network string. */
|
||||
int size() const { return (int)m_string.size(); }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a byte pointer to the content of the network string. */
|
||||
uint8_t* getBytes() { return &m_string[0]; };
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a byte pointer to the content of the network string. */
|
||||
const uint8_t* getBytes() const { return &m_string[0]; };
|
||||
} // addString
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Template to get n bytes from a buffer into a single data type. */
|
||||
template<typename T, size_t n>
|
||||
T get(int pos) const
|
||||
{
|
||||
int a = n;
|
||||
T result = 0;
|
||||
int offset = m_current_offset + pos + n -1;
|
||||
while (a--)
|
||||
{
|
||||
result <<= 8; // offset one byte
|
||||
// add the data to result
|
||||
result += ((uint8_t)(m_string[pos + n - 1 - a]) & 0xff);
|
||||
// add the data to result
|
||||
result += m_buffer[offset - a];
|
||||
}
|
||||
return result;
|
||||
} // get(int pos)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Another function for n == 1 to surpress warnings in clang
|
||||
/** Another function for n == 1 to surpress warnings in clang. */
|
||||
template<typename T>
|
||||
T get(int pos) const
|
||||
{
|
||||
return m_string[pos];
|
||||
return m_buffer[pos];
|
||||
} // get
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor, sets the protocol type of this message. */
|
||||
BareNetworkString(int capacity=16)
|
||||
{
|
||||
m_buffer.reserve(capacity);
|
||||
m_current_offset = 0;
|
||||
} // BareNetworkString
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a standard integer. */
|
||||
inline int getInt(int pos = 0) const { return get<int, 4>(pos); }
|
||||
BareNetworkString(const std::string &s)
|
||||
{
|
||||
m_current_offset = 0;
|
||||
encodeString(s);
|
||||
} // BareNetworkString
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a standard unsigned integer. */
|
||||
inline uint32_t getUInt(int pos = 0) const { return get<uint32_t, 4>(pos); }
|
||||
/** Initialises the string with a sequence of characters. */
|
||||
BareNetworkString(const char *data, int len)
|
||||
{
|
||||
m_current_offset = 0;
|
||||
m_buffer.resize(len);
|
||||
memcpy(m_buffer.data(), data, len);
|
||||
} // BareNetworkString
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
BareNetworkString& encodeString(const std::string &value);
|
||||
BareNetworkString& encodeString(const irr::core::stringw &value);
|
||||
int decodeString(int n, std::string *out) const;
|
||||
int decodeStringW(int n, irr::core::stringw *out) const;
|
||||
std::string getLogMessage(const std::string &indent="") const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a byte pointer to the content of the network string. */
|
||||
char* getData() { return (char*)(m_buffer.data()); };
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a byte pointer to the content of the network string. */
|
||||
const char* getData() const { return (char*)(m_buffer.data()); };
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the remaining length of the network string. */
|
||||
unsigned int size() const { return (int)m_buffer.size()-m_current_offset; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// All functions related to adding data to a network string
|
||||
/** Add 8 bit unsigned int. */
|
||||
BareNetworkString& addUInt8(const uint8_t value)
|
||||
{
|
||||
m_buffer.push_back(value);
|
||||
return *this;
|
||||
} // addUInt8
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a single character to the string. */
|
||||
BareNetworkString& addChar(const char value)
|
||||
{
|
||||
m_buffer.push_back((uint8_t)(value));
|
||||
return *this;
|
||||
} // addChar
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds 16 bit unsigned int. */
|
||||
BareNetworkString& addUInt16(const uint16_t value)
|
||||
{
|
||||
m_buffer.push_back((value >> 8) & 0xff);
|
||||
m_buffer.push_back(value & 0xff);
|
||||
return *this;
|
||||
} // addUInt16
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds unsigned 32 bit integer. */
|
||||
BareNetworkString& addUInt32(const uint32_t& value)
|
||||
{
|
||||
m_buffer.push_back((value >> 24) & 0xff);
|
||||
m_buffer.push_back((value >> 16) & 0xff);
|
||||
m_buffer.push_back((value >> 8) & 0xff);
|
||||
m_buffer.push_back( value & 0xff);
|
||||
return *this;
|
||||
} // addUInt32
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a 4 byte floating point value. */
|
||||
BareNetworkString& addFloat(const float value)
|
||||
{
|
||||
uint32_t *p = (uint32_t*)&value;
|
||||
return addUInt32(*p);
|
||||
} // addFloat
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds the content of another network string. It only copies data which
|
||||
* has not been 'removed' (i.e. skipped). */
|
||||
BareNetworkString& operator+=(BareNetworkString const& value)
|
||||
{
|
||||
m_buffer.insert(m_buffer.end(),
|
||||
value.m_buffer.begin()+value.m_current_offset,
|
||||
value.m_buffer.end() );
|
||||
return *this;
|
||||
} // operator+=
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds the xyz components of a Vec3 to the string. */
|
||||
BareNetworkString& add(const Vec3 &xyz)
|
||||
{
|
||||
return addFloat(xyz.getX()).addFloat(xyz.getY()).addFloat(xyz.getZ());
|
||||
} // add
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds the four components of a quaternion. */
|
||||
BareNetworkString& add(const btQuaternion &quat)
|
||||
{
|
||||
return addFloat(quat.getX()).addFloat(quat.getY())
|
||||
.addFloat(quat.getZ()).addFloat(quat.getW());
|
||||
} // add
|
||||
|
||||
// Functions related to getting data from a network string
|
||||
// ------------------------------------------------------------------------
|
||||
/** Ignore the next num_bytes from the message. */
|
||||
void removeFront(unsigned int num_bytes)
|
||||
{
|
||||
assert(m_current_offset + num_bytes <= m_buffer.size());
|
||||
m_current_offset += num_bytes;
|
||||
} // removeFront
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Gets the byte at the specified position (taking current offset into
|
||||
* account). */
|
||||
uint8_t operator[](const int pos) const
|
||||
{
|
||||
return m_buffer[m_current_offset + pos];
|
||||
} // operator[]
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a unsigned 32 bit integer. */
|
||||
inline uint32_t getUInt32(int pos = 0) const { return get<uint32_t, 4>(pos); }
|
||||
@@ -329,215 +247,144 @@ public:
|
||||
inline uint16_t getUInt16(int pos=0) const { return get<uint16_t, 2>(pos); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns an unsigned 8-bit integer. */
|
||||
inline uint8_t getUInt8(int pos = 0) const { return get<uint8_t>(pos); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a character. */
|
||||
inline char getChar(int pos = 0) const { return get<char>(pos); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns an unsigned character. */
|
||||
inline unsigned char getUChar(int pos = 0) const
|
||||
inline uint8_t getUInt8(int pos = 0) const
|
||||
{
|
||||
return get<unsigned char>(pos);
|
||||
} // getUChar
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a standard integer. */
|
||||
inline int gi(int pos = 0) const { return get<int, 4>(pos); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Retrusn an unsigned standard integer. */
|
||||
inline uint32_t gui(int pos = 0) const { return get<uint32_t, 4>(pos); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns an unsigned 32-bit integer. */
|
||||
inline uint32_t gui32(int pos = 0) const { return get<uint32_t, 4>(pos); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns an unsigned 16-bit integer. */
|
||||
inline uint16_t gui16(int pos = 0) const { return get<uint16_t, 2>(pos); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns an unsigned 8-bit integer. */
|
||||
inline uint8_t gui8(int pos = 0) const { return get<uint8_t>(pos); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return a character. */
|
||||
inline char gc(int pos = 0) const { return get<char>(pos); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return an unsigned character. */
|
||||
inline unsigned char guc(int pos = 0) const
|
||||
{
|
||||
return get<unsigned char>(pos);
|
||||
} // guc
|
||||
return m_buffer[m_current_offset + pos];
|
||||
} // getUInt8
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a 4-byte floating point value. */
|
||||
float getFloat(int pos = 0) const //!< BEWARE OF PRECISION
|
||||
/** Gets a 4 byte floating point value. */
|
||||
float getFloat(int pos=0) const
|
||||
{
|
||||
FloatAsInt f_as_i;
|
||||
for (int i = 0; i < 4; i++)
|
||||
f_as_i.i[i] = m_string[pos + i];
|
||||
return f_as_i.f;
|
||||
} // getFloat
|
||||
uint32_t u = getUInt32(pos);
|
||||
float f;
|
||||
// Doig a "return *(float*)&u;" appears to be more efficient,
|
||||
// but it can create incorrect code on higher optimisation: c++
|
||||
// makes the assumption that pointer of different types never
|
||||
// overlap. So the compiler can assume that the int pointer (&u)
|
||||
// and float pointer do point to different aras, so there read
|
||||
// (*(float*) can be done before the write to u (and then the
|
||||
// write to u is basically a no-op and can be removed, too).
|
||||
// Using a union of int and float is not valid either, there
|
||||
// is no guarantee that writing to the int part of the union
|
||||
// will affect the float part. So, an explicit memcpy is the
|
||||
// more or less only portable guaranteed to be correct way of
|
||||
// converting the int to a float.
|
||||
memcpy(&f, &u, sizeof(float));
|
||||
return f;
|
||||
} // getFloat
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
//! Functions to get while removing
|
||||
template<typename T, size_t n>
|
||||
T getAndRemove(int pos)
|
||||
/** Gets a Vec3. */
|
||||
Vec3 getVec3(int pos=0) 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
|
||||
}
|
||||
remove(pos, n);
|
||||
return result;
|
||||
} // getAndRemove
|
||||
return Vec3(getFloat(pos), getFloat(pos+4), getFloat(pos+8));
|
||||
} // getVec3
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Another function for n == 1 to surpress warnings in clang
|
||||
template<typename T>
|
||||
T getAndRemove(int pos)
|
||||
/** Gets a Vec3. */
|
||||
btQuaternion getQuat(int pos=0) const
|
||||
{
|
||||
T result = m_string[pos];
|
||||
remove(pos, 1);
|
||||
return result;
|
||||
} // getAndRemove
|
||||
return btQuaternion(getFloat(pos), getFloat(pos+ 4),
|
||||
getFloat(pos+8), getFloat(pos+12) );
|
||||
} // getQuat
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
}; // class BareNetworkString
|
||||
|
||||
|
||||
// ============================================================================
|
||||
|
||||
/** A new implementation of NetworkString, which has a fixed format:
|
||||
* Byte 0: The type of the message, which is actually a bit field:
|
||||
* bit 7: if set, the message needs to be handled synchronously,
|
||||
* otherwise it can be handled by the separate protocol
|
||||
* manager thread.
|
||||
* bits 6-0: The protocol ID, which identifies the receiving protocol
|
||||
* for this message.
|
||||
* Byte 1-4: A token to authenticate the sender.
|
||||
*
|
||||
* Otherwise this class offers template functions to add arbitrary variables,
|
||||
* and retrieve them again. It kept the functionality of 'removing' bytes
|
||||
* (e.g. the ProtocolManager would remove the first byte - protocol type -
|
||||
* so that the protocols would not see this byte). But this is implemented
|
||||
* now by using a base pointer (and not by moving the buffer content).
|
||||
*/
|
||||
class NetworkString : public BareNetworkString
|
||||
{
|
||||
public:
|
||||
static void unitTesting();
|
||||
|
||||
/** Constructor for a message to be sent. It sets the
|
||||
* protocol type of this message. It adds 5 bytes to the capacity:
|
||||
* 1 byte for the protocol type, and 4 bytes for the token. */
|
||||
NetworkString(ProtocolType type, int capacity=16)
|
||||
: BareNetworkString(capacity+5)
|
||||
{
|
||||
m_buffer.push_back(type);
|
||||
addUInt32(0); // add dummy token for now
|
||||
} // NetworkString
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
inline int getAndRemoveInt(int pos = 0)
|
||||
/** Constructor for a received message. It automatically ignored the first
|
||||
* 5 bytes which contain the type and token. Those will be access using
|
||||
* special functions. */
|
||||
NetworkString(const uint8_t *data, int len)
|
||||
: BareNetworkString((char*)data, len)
|
||||
{
|
||||
return getAndRemove<int, 4>(pos);
|
||||
} // getAndRemoveInt
|
||||
m_current_offset = 5; // ignore type and token
|
||||
} // NetworkString
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
inline uint32_t getAndRemoveUInt(int pos = 0)
|
||||
/** Returns the protocol type of this message. */
|
||||
ProtocolType getProtocolType() const
|
||||
{
|
||||
return getAndRemove<uint32_t, 4>(pos);
|
||||
} // getAndRemoveUInt
|
||||
assert(!m_buffer.empty());
|
||||
return (ProtocolType)(m_buffer[0] & ~PROTOCOL_SYNCHRONOUS);
|
||||
} // getProtocolType
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
inline uint32_t getAndRemoveUInt32(int pos = 0)
|
||||
/** Sets if this message is to be sent synchronous or asynchronous. */
|
||||
void setSynchronous(bool b)
|
||||
{
|
||||
return getAndRemove<uint32_t, 4>(pos);
|
||||
} // getAndRemoveUInt32
|
||||
|
||||
if(b)
|
||||
m_buffer[0] |= PROTOCOL_SYNCHRONOUS;
|
||||
else
|
||||
m_buffer[0] &= ~PROTOCOL_SYNCHRONOUS;
|
||||
} // setSynchronous
|
||||
// ------------------------------------------------------------------------
|
||||
inline uint16_t getAndRemoveUInt16(int pos = 0)
|
||||
/** Returns if this message is synchronous or not. */
|
||||
bool isSynchronous() const
|
||||
{
|
||||
return getAndRemove<uint16_t, 2>(pos);
|
||||
} // getAndRemoveUInt16
|
||||
return (m_buffer[0] & PROTOCOL_SYNCHRONOUS) == PROTOCOL_SYNCHRONOUS;
|
||||
} // isSynchronous
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets a token for a message. Note that the token in an already
|
||||
* assembled message might be updated (e.g. if the same message is sent
|
||||
* from the server to a set of clients). */
|
||||
void setToken(uint32_t token)
|
||||
{
|
||||
// Make sure there is enough space for the token:
|
||||
if(m_buffer.size()<5)
|
||||
m_buffer.resize(5);
|
||||
|
||||
m_buffer[1] = (token >> 24) & 0xff;
|
||||
m_buffer[2] = (token >> 16) & 0xff;
|
||||
m_buffer[3] = (token >> 8) & 0xff;
|
||||
m_buffer[4] = token & 0xff;
|
||||
} // setToken
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
inline uint8_t getAndRemoveUInt8(int pos = 0)
|
||||
/** Returns if the security token of this message is the same as the
|
||||
* specified token. */
|
||||
uint32_t getToken() const
|
||||
{
|
||||
return getAndRemove<uint8_t>(pos);
|
||||
} // getAndRemoveUInt8
|
||||
// ------------------------------------------------------------------------
|
||||
inline char getAndRemoveChar(int pos = 0)
|
||||
{
|
||||
return getAndRemove<char>(pos);
|
||||
} // getAndRemoveChar
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
inline unsigned char getAndRemoveUChar(int pos = 0)
|
||||
{
|
||||
return getAndRemove<unsigned char>(pos);
|
||||
} // getAndRemoveUChar
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
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);
|
||||
} // getAndRemoveDouble
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Get and remove a 4 byte floating point value. */
|
||||
float getAndRemoveFloat(int pos = 0) //!< BEWARE OF PRECISION
|
||||
{
|
||||
FloatAsInt f_as_i;
|
||||
for (int i = 0; i < 4; i++)
|
||||
f_as_i.i[i] = m_string[pos + i];
|
||||
return f_as_i.f;
|
||||
remove(pos, 4);
|
||||
} // getAndRemoveFloat
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Removes a 8 bit unsigned int. */
|
||||
inline NetworkString& gui8(uint8_t* dst)
|
||||
{
|
||||
*dst = getAndRemoveUInt8(0);
|
||||
return *this;
|
||||
} // gui8
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a 16 bit integer. */
|
||||
inline NetworkString& gui16(uint16_t* dst)
|
||||
{
|
||||
*dst = getAndRemoveUInt16(0);
|
||||
return *this;
|
||||
} // gui16
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a 32 bit integer. */
|
||||
inline NetworkString& gui32(uint32_t* dst)
|
||||
{
|
||||
*dst = getAndRemoveUInt32(0);
|
||||
return *this;
|
||||
} // gui32
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a 32 bit integer. */
|
||||
inline NetworkString& gui(uint32_t* dst)
|
||||
{
|
||||
*dst = getAndRemoveUInt32(0);
|
||||
return *this;
|
||||
} // gui
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns 4 byte integer. */
|
||||
inline NetworkString& gi(int* dst)
|
||||
{
|
||||
*dst = getAndRemoveInt(0);
|
||||
return *this;
|
||||
} // gi
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a single character. */
|
||||
inline NetworkString& gc(char* dst)
|
||||
{
|
||||
*dst = getAndRemoveChar(0);
|
||||
return *this;
|
||||
} // gc
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns an unsigned character. */
|
||||
inline NetworkString& guc(uchar* dst)
|
||||
{
|
||||
*dst = getAndRemoveUChar(0);
|
||||
return *this;
|
||||
} // guc
|
||||
// ------------------------------------------------------------------------
|
||||
/** Reads the three components of a Vec3 from the given position. */
|
||||
NetworkString& get(Vec3 *xyz, int pos)
|
||||
{
|
||||
xyz->setX(getFloat(pos ));
|
||||
xyz->setY(getFloat(pos+4));
|
||||
xyz->setZ(getFloat(pos+8));
|
||||
return *this;
|
||||
} // addVec3
|
||||
// ------------------------------------------------------------------------
|
||||
/** Reads the four components of a quaternion from the given position. */
|
||||
NetworkString& get(btQuaternion *quat, int pos)
|
||||
{
|
||||
quat->setX(getFloat(pos ));
|
||||
quat->setY(getFloat(pos+ 4));
|
||||
quat->setZ(getFloat(pos+ 8));
|
||||
quat->setW(getFloat(pos+12));
|
||||
return *this;
|
||||
} // addVec3
|
||||
// Since m_current_offset might be set, we need to make sure
|
||||
// to really access bytes 1-4
|
||||
return getUInt32(1-m_current_offset);
|
||||
} // getToken
|
||||
|
||||
}; // class NetworkString
|
||||
|
||||
NetworkString operator+(NetworkString const& a, NetworkString const& b);
|
||||
|
||||
#endif // NETWORK_STRING_HPP
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
#include "network/event.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
@@ -47,39 +48,30 @@ Protocol::~Protocol()
|
||||
} // ~Protocol
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool Protocol::checkDataSizeAndToken(Event* event, int minimum_size)
|
||||
/** Returns a network string with the given type.
|
||||
* \capacity Default preallocated size for the message.
|
||||
*/
|
||||
NetworkString* Protocol::getNetworkString(int capacity)
|
||||
{
|
||||
const NetworkString &data = event->data();
|
||||
if (data.size() < minimum_size || data[0] != 4)
|
||||
{
|
||||
Log::warn("Protocol", "Receiving a badly "
|
||||
"formated message. Size is %d and first byte %d",
|
||||
data.size(), data[0]);
|
||||
return false;
|
||||
}
|
||||
STKPeer* peer = event->getPeer();
|
||||
uint32_t token = data.gui32(1);
|
||||
if (token != peer->getClientServerToken())
|
||||
{
|
||||
Log::warn("Protocol", "Peer sending bad token. Request "
|
||||
"aborted.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} // checkDataSizeAndToken
|
||||
return new NetworkString(m_type, capacity);
|
||||
} // getNetworkString
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool Protocol::isByteCorrect(Event* event, int byte_nb, int value)
|
||||
/** Checks if the message has at least the specified size, and if not prints
|
||||
* a warning message including the message content.
|
||||
* \return True if the message is long enough, false otherwise.
|
||||
*/
|
||||
bool Protocol::checkDataSize(Event* event, unsigned int minimum_size)
|
||||
{
|
||||
const NetworkString &data = event->data();
|
||||
if (data[byte_nb] != value)
|
||||
if (data.size() < minimum_size)
|
||||
{
|
||||
Log::info("Protocol", "Bad byte at pos %d. %d "
|
||||
"should be %d", byte_nb, data[byte_nb], value);
|
||||
Log::warn("Protocol", "Receiving a badly formated message:");
|
||||
Log::warn("Protocol", data.getLogMessage().c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} // isByteCorrect
|
||||
} // checkDataSize
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Starts a request in the protocol manager to start this protocol.
|
||||
@@ -117,50 +109,22 @@ void Protocol::requestTerminate()
|
||||
/** Sends a message to all peers, inserting the peer's token into the message.
|
||||
* The message is composed of a 1-byte message (usually the message type)
|
||||
* followed by the token of this client and then actual message).
|
||||
* \param type The first byte of the combined message.
|
||||
* \param message The actual message content.
|
||||
*/
|
||||
void Protocol::sendMessageToPeersChangingToken(uint8_t type,
|
||||
const NetworkString &message)
|
||||
void Protocol::sendMessageToPeersChangingToken(NetworkString *message,
|
||||
bool reliable)
|
||||
{
|
||||
const std::vector<STKPeer*> &peers = STKHost::get()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString combined(1+4+message.size());
|
||||
combined.addUInt8(type).addUInt8(4)
|
||||
.addUInt32(peers[i]->getClientServerToken());
|
||||
combined+=message;
|
||||
ProtocolManager::getInstance()->sendMessage(this, peers[i], combined);
|
||||
peers[i]->sendPacket(message, reliable);
|
||||
}
|
||||
} // sendMessageToPeersChangingToken
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Protocol::sendMessage(const NetworkString& message, bool reliable)
|
||||
/** Sends a message from a client to the server.
|
||||
*/
|
||||
void Protocol::sendToServer(NetworkString *message, bool reliable)
|
||||
{
|
||||
ProtocolManager::getInstance()->sendMessage(this, message, reliable,
|
||||
/*synchronous*/false);
|
||||
STKHost::get()->sendToServer(message, reliable);
|
||||
} // sendMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Protocol::sendSynchronousMessage(const NetworkString& message,
|
||||
bool reliable)
|
||||
{
|
||||
ProtocolManager::getInstance()->sendMessage(this, message, reliable,
|
||||
/*synchron*/true);
|
||||
} // sendMessage
|
||||
// ----------------------------------------------------------------------------
|
||||
void Protocol::sendMessage(STKPeer* peer, const NetworkString& message,
|
||||
bool reliable)
|
||||
{
|
||||
ProtocolManager::getInstance()->sendMessage(this, peer, message, reliable,
|
||||
/*synchronous*/false);
|
||||
} // sendMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Protocol::sendSynchronousMessage(STKPeer* peer,
|
||||
const NetworkString& message,
|
||||
bool reliable)
|
||||
{
|
||||
ProtocolManager::getInstance()->sendMessage(this, peer, message, reliable,
|
||||
/*synchronous*/true);
|
||||
} // sendSynchronousMessage
|
||||
|
||||
@@ -23,12 +23,14 @@
|
||||
#ifndef PROTOCOL_HPP
|
||||
#define PROTOCOL_HPP
|
||||
|
||||
#include "network/network_string.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
class Event;
|
||||
class NetworkString;
|
||||
class STKPeer;
|
||||
|
||||
|
||||
@@ -121,18 +123,12 @@ public:
|
||||
virtual void asynchronousUpdate() = 0;
|
||||
|
||||
/// functions to check incoming data easily
|
||||
bool checkDataSizeAndToken(Event* event, int minimum_size);
|
||||
bool isByteCorrect(Event* event, int byte_nb, int value);
|
||||
void sendMessageToPeersChangingToken(uint8_t type,
|
||||
const NetworkString &message);
|
||||
void sendMessage(const NetworkString& message,
|
||||
bool reliable = true);
|
||||
void sendMessage(STKPeer* peer, const NetworkString& message,
|
||||
bool reliable = true);
|
||||
void sendSynchronousMessage(const NetworkString& message,
|
||||
bool reliable=true);
|
||||
void sendSynchronousMessage(STKPeer* peer, const NetworkString& message,
|
||||
bool reliable = true);
|
||||
NetworkString* getNetworkString(int capacity=16);
|
||||
bool checkDataSize(Event* event, unsigned int minimum_size);
|
||||
void sendMessageToPeersChangingToken(NetworkString *message,
|
||||
bool reliable = true);
|
||||
void sendToServer(NetworkString *message,
|
||||
bool reliable = true);
|
||||
void requestStart();
|
||||
void requestPause();
|
||||
void requestUnpause();
|
||||
|
||||
@@ -110,8 +110,7 @@ void ProtocolManager::propagateEvent(Event* event)
|
||||
{
|
||||
if (event->data().size() > 0)
|
||||
{
|
||||
searched_protocol = (ProtocolType)(event->data()[0]);
|
||||
event->removeFront(1);
|
||||
searched_protocol = event->data().getProtocolType();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -125,14 +124,7 @@ void ProtocolManager::propagateEvent(Event* event)
|
||||
Log::verbose("ProtocolManager", "Received event for protocols of type %d",
|
||||
searched_protocol);
|
||||
|
||||
bool is_synchronous = false;
|
||||
if(searched_protocol & PROTOCOL_SYNCHRONOUS)
|
||||
{
|
||||
is_synchronous = true;
|
||||
// Reset synchronous flag to restore original protocol id
|
||||
searched_protocol = ProtocolType(searched_protocol &
|
||||
~PROTOCOL_SYNCHRONOUS );
|
||||
}
|
||||
|
||||
std::vector<unsigned int> protocols_ids;
|
||||
m_protocols.lock();
|
||||
for (unsigned int i = 0; i < m_protocols.getData().size() ; i++)
|
||||
@@ -148,17 +140,25 @@ void ProtocolManager::propagateEvent(Event* event)
|
||||
m_protocols.unlock();
|
||||
|
||||
// no protocol was aimed, show the msg to debug
|
||||
if (searched_protocol == PROTOCOL_NONE)
|
||||
if (searched_protocol == PROTOCOL_NONE &&
|
||||
event->getType() != EVENT_TYPE_DISCONNECTED)
|
||||
{
|
||||
Log::debug("ProtocolManager", "NO PROTOCOL : Message is \"%s\"",
|
||||
event->data().std_string().c_str());
|
||||
if(event->getType()==EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
Log::warn("ProtocolManager", "NO PROTOCOL. Message is:");
|
||||
Log::warn("ProtocolManager", event->data().getLogMessage().c_str());
|
||||
}
|
||||
else
|
||||
Log::debug("ProtocolManager", "NO PROTOCOL, no data");
|
||||
}
|
||||
|
||||
if (protocols_ids.size() != 0)
|
||||
{
|
||||
EventProcessingInfo epi;
|
||||
epi.m_arrival_time = (double)StkTime::getTimeSinceEpoch();
|
||||
epi.m_is_synchronous = is_synchronous;
|
||||
// Only message events will optionally be delivered synchronously
|
||||
epi.m_is_synchronous = event->getType()==EVENT_TYPE_MESSAGE &&
|
||||
event->data().isSynchronous();
|
||||
epi.m_event = event;
|
||||
epi.m_protocols_ids = protocols_ids;
|
||||
// Add the event to the queue. After the event is handled
|
||||
@@ -176,46 +176,6 @@ void ProtocolManager::propagateEvent(Event* event)
|
||||
m_events_to_process.unlock();
|
||||
} // propagateEvent
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ProtocolManager::sendMessage(Protocol* sender, const NetworkString& message,
|
||||
bool reliable, bool send_synchronously)
|
||||
{
|
||||
NetworkString new_message(1+message.size());
|
||||
ProtocolType type = sender->getProtocolType();
|
||||
// Set flag if the message must be handled synchronously on arrivat
|
||||
if(send_synchronously)
|
||||
type = ProtocolType(type | PROTOCOL_SYNCHRONOUS);
|
||||
new_message.ai8(type); // add one byte to add protocol type
|
||||
new_message += message;
|
||||
STKHost::get()->sendMessage(new_message, reliable);
|
||||
} // sendMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ProtocolManager::sendMessage(Protocol* sender, STKPeer* peer,
|
||||
const NetworkString& message, bool reliable,
|
||||
bool send_synchronously)
|
||||
{
|
||||
NetworkString new_message(1+message.size());
|
||||
ProtocolType type = sender->getProtocolType();
|
||||
// Set flag if the message must be handled synchronously on arrivat
|
||||
if(send_synchronously)
|
||||
type = ProtocolType(type | PROTOCOL_SYNCHRONOUS);
|
||||
new_message.ai8(type); // add one byte to add protocol type
|
||||
new_message += message;
|
||||
peer->sendPacket(new_message, reliable);
|
||||
} // sendMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ProtocolManager::sendMessageExcept(Protocol* sender, STKPeer* peer,
|
||||
const NetworkString& message,
|
||||
bool reliable)
|
||||
{
|
||||
NetworkString new_message(1+message.size());
|
||||
new_message.ai8(sender->getProtocolType()); // add one byte to add protocol type
|
||||
new_message += message;
|
||||
STKHost::get()->sendPacketExcept(peer, new_message, reliable);
|
||||
} // sendMessageExcept
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** \brief Asks the manager to start a protocol.
|
||||
* This function will store the request, and process it at a time it is
|
||||
|
||||
@@ -162,17 +162,6 @@ private:
|
||||
public:
|
||||
virtual void abort();
|
||||
virtual void propagateEvent(Event* event);
|
||||
virtual void sendMessage(Protocol* sender,
|
||||
const NetworkString& message,
|
||||
bool reliable = true,
|
||||
bool send_synchronously = false);
|
||||
virtual void sendMessage(Protocol* sender, STKPeer* peer,
|
||||
const NetworkString& message,
|
||||
bool reliable = true,
|
||||
bool send_synchronously = false);
|
||||
virtual void sendMessageExcept(Protocol* sender, STKPeer* peer,
|
||||
const NetworkString& message,
|
||||
bool reliable = true);
|
||||
virtual uint32_t requestStart(Protocol* protocol);
|
||||
virtual void requestPause(Protocol* protocol);
|
||||
virtual void requestUnpause(Protocol* protocol);
|
||||
|
||||
@@ -60,44 +60,41 @@ void ClientLobbyRoomProtocol::setup()
|
||||
|
||||
void ClientLobbyRoomProtocol::requestKartSelection(const std::string &kart_name)
|
||||
{
|
||||
NetworkString request(6+1+kart_name.size());
|
||||
// size_token (4), token, size kart name, kart name
|
||||
request.ai8(LE_KART_SELECTION).ai8(4).ai32(m_server->getClientServerToken())
|
||||
.encodeString(kart_name);
|
||||
sendMessage(request, true);
|
||||
NetworkString *request = getNetworkString(2+kart_name.size());
|
||||
request->addUInt8(LE_KART_SELECTION).encodeString(kart_name);
|
||||
sendToServer(request, /*reliable*/ true);
|
||||
delete request;
|
||||
} // requestKartSelection
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteMajor(uint32_t major)
|
||||
{
|
||||
NetworkString request(8);
|
||||
// size_token (4), token, size major(1),major
|
||||
request.ai8(LE_VOTE_MAJOR).ai8(4)
|
||||
.ai32(m_server->getClientServerToken()).ai8(4).addUInt32(major);
|
||||
sendMessage(request, true);
|
||||
NetworkString *request = getNetworkString(8);
|
||||
request->addUInt8(LE_VOTE_MAJOR).addUInt8(4)
|
||||
.addUInt8(4).addUInt32(major);
|
||||
sendToServer(request, true);
|
||||
delete request;
|
||||
} // voteMajor
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteRaceCount(uint8_t count)
|
||||
{
|
||||
NetworkString request(8);
|
||||
// size_token (4), token, size race count(1), count
|
||||
request.ai8(LE_VOTE_RACE_COUNT).ai8(4)
|
||||
.ai32(m_server->getClientServerToken()).ai8(1).ai8(count);
|
||||
sendMessage(request, true);
|
||||
NetworkString *request = getNetworkString(8);
|
||||
request->addUInt8(LE_VOTE_RACE_COUNT).addUInt8(count);
|
||||
sendToServer(request, true);
|
||||
delete request;
|
||||
} // voteRaceCount
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteMinor(uint32_t minor)
|
||||
{
|
||||
NetworkString request(8);
|
||||
// size_token (4), token, size minor(1),minor
|
||||
request.ai8(LE_VOTE_MINOR).ai8(4).ai32(m_server->getClientServerToken())
|
||||
.ai8(4).addUInt32(minor);
|
||||
sendMessage(request, true);
|
||||
NetworkString *request = getNetworkString(8);
|
||||
request->addUInt8(LE_VOTE_MINOR).addUInt32(minor);
|
||||
sendToServer(request, true);
|
||||
delete request;
|
||||
} // voteMinor
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -105,33 +102,30 @@ void ClientLobbyRoomProtocol::voteMinor(uint32_t minor)
|
||||
void ClientLobbyRoomProtocol::voteTrack(const std::string &track,
|
||||
uint8_t track_nb)
|
||||
{
|
||||
NetworkString request(8+1+track.size());
|
||||
// size_token (4), token, size track, track, size #track, #track
|
||||
request.ai8(LE_VOTE_TRACK).ai8(4).ai32(m_server->getClientServerToken())
|
||||
.encodeString(track).ai8(1).ai8(track_nb);
|
||||
sendMessage(request, true);
|
||||
NetworkString *request = getNetworkString(2+1+track.size());
|
||||
request->addUInt8(LE_VOTE_TRACK).addUInt8(track_nb).encodeString(track);
|
||||
sendToServer(request, true);
|
||||
delete request;
|
||||
} // voteTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteReversed(bool reversed, uint8_t track_nb)
|
||||
{
|
||||
NetworkString request(9);
|
||||
// size_token (4), token, size reversed(1),reversed, size #track, #track
|
||||
request.ai8(LE_VOTE_REVERSE).ai8(4).ai32(m_server->getClientServerToken())
|
||||
.ai8(1).ai8(reversed).ai8(1).ai8(track_nb);
|
||||
sendMessage(request, true);
|
||||
NetworkString *request = getNetworkString(9);
|
||||
request->addUInt8(LE_VOTE_REVERSE).addUInt8(reversed).addUInt8(track_nb);
|
||||
sendToServer(request, true);
|
||||
delete request;
|
||||
} // voteReversed
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::voteLaps(uint8_t laps, uint8_t track_nb)
|
||||
{
|
||||
NetworkString request(10);
|
||||
// size_token (4), token, size laps(1),laps, size #track, #track
|
||||
request.ai8(LE_VOTE_LAPS).ai8(4).ai32(m_server->getClientServerToken())
|
||||
.ai8(1).ai8(laps).ai8(1).ai8(track_nb);
|
||||
sendMessage(request, true);
|
||||
NetworkString *request = getNetworkString(10);
|
||||
request->addUInt8(LE_VOTE_LAPS).addUInt8(laps).addUInt8(track_nb);
|
||||
sendToServer(request, true);
|
||||
delete request;
|
||||
} // voteLaps
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -151,14 +145,14 @@ bool ClientLobbyRoomProtocol::notifyEvent(Event* event)
|
||||
assert(m_setup); // assert that the setup exists
|
||||
if (event->getType() == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
const NetworkString &data = event->data();
|
||||
NetworkString &data = event->data();
|
||||
assert(data.size()); // assert that data isn't empty
|
||||
uint8_t message_type = data[0];
|
||||
if (message_type != LE_KART_SELECTION_UPDATE &&
|
||||
message_type != LE_RACE_FINISHED )
|
||||
return false; // don't treat the event
|
||||
|
||||
event->removeFront(1);
|
||||
data.removeFront(1);
|
||||
Log::info("ClientLobbyRoomProtocol", "Synchronous message of type %d",
|
||||
message_type);
|
||||
if (message_type == LE_KART_SELECTION_UPDATE) // kart selection update
|
||||
@@ -178,11 +172,11 @@ bool ClientLobbyRoomProtocol::notifyEventAsynchronous(Event* event)
|
||||
assert(m_setup); // assert that the setup exists
|
||||
if (event->getType() == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
const NetworkString &data = event->data();
|
||||
NetworkString &data = event->data();
|
||||
assert(data.size()); // assert that data isn't empty
|
||||
uint8_t message_type = data[0];
|
||||
|
||||
event->removeFront(1);
|
||||
data.removeFront(1);
|
||||
Log::info("ClientLobbyRoomProtocol", "Asynchronous message of type %d",
|
||||
message_type);
|
||||
switch(message_type)
|
||||
@@ -244,11 +238,13 @@ void ClientLobbyRoomProtocol::update()
|
||||
|
||||
std::string name_u8 = StringUtils::wideToUtf8(name);
|
||||
const std::string &password = NetworkConfig::get()->getPassword();
|
||||
NetworkString ns(6+1+name_u8.size()+1+password.size());
|
||||
NetworkString *ns = getNetworkString(6+1+name_u8.size()
|
||||
+1+password.size());
|
||||
// 4 (size of id), global id
|
||||
ns.ai8(LE_CONNECTION_REQUESTED).encodeString(name)
|
||||
ns->addUInt8(LE_CONNECTION_REQUESTED).encodeString(name)
|
||||
.encodeString(NetworkConfig::get()->getPassword());
|
||||
sendMessage(ns);
|
||||
sendToServer(ns);
|
||||
delete ns;
|
||||
m_state = REQUESTING_CONNECTION;
|
||||
}
|
||||
break;
|
||||
@@ -293,25 +289,19 @@ void ClientLobbyRoomProtocol::update()
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2s
|
||||
* ---------------------------------------
|
||||
* Size | 1 | 1 | |
|
||||
* Data | 1 | 0 <= race id < 16 | player name|
|
||||
* ---------------------------------------
|
||||
* Byte 0 1 2
|
||||
* -------------------------------------
|
||||
* Size | 1 | 1 | |
|
||||
* Data | player_id | hostid | player name |
|
||||
* -------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::newPlayer(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 2)) return;
|
||||
const NetworkString &data = event->data();
|
||||
if (data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol",
|
||||
"A message notifying a new player wasn't formated "
|
||||
"as expected.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t player_id = data.gui8(1);
|
||||
|
||||
uint8_t player_id = data[0];
|
||||
uint8_t hostid = data[1];
|
||||
core::stringw name;
|
||||
data.decodeStringW(2, &name);
|
||||
// FIXME need adjusting when splitscreen is used/
|
||||
@@ -341,22 +331,17 @@ void ClientLobbyRoomProtocol::newPlayer(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2
|
||||
* -------------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | 1 | 0 <= race id < 16 |
|
||||
* -------------------------
|
||||
* Byte 0
|
||||
* -------------
|
||||
* Size | 1 |
|
||||
* Data | player id |
|
||||
* -------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 1)) return;
|
||||
|
||||
const NetworkString &data = event->data();
|
||||
if (data.size() != 2 || data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol",
|
||||
"A message notifying a new player wasn't formated "
|
||||
"as expected.");
|
||||
return;
|
||||
}
|
||||
if (m_setup->removePlayer(event->getPeer()->getPlayerProfile()))
|
||||
{
|
||||
Log::info("ClientLobbyRoomProtocol", "Peer removed successfully.");
|
||||
@@ -375,23 +360,18 @@ void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2 3 7 8 9
|
||||
* -----------------------------------------------------------------------------
|
||||
* Size | 1 | 1 | 1 | 4 | 1 | 1 | |
|
||||
* Data | 1 | 0 <= race id < 16 | 4 | priv token | hostid | authorised |playernames* |
|
||||
* ------------------------------------------------------------------------------
|
||||
* Byte 0 1 2 3
|
||||
* ---------------------------------------------------------
|
||||
* Size | 1 | 1 | 1 | |
|
||||
* Data | player_id| hostid | authorised |playernames* |
|
||||
* ---------------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
|
||||
{
|
||||
// At least 3 bytes should remain now
|
||||
if(!checkDataSize(event, 3)) return;
|
||||
|
||||
NetworkString &data = event->data();
|
||||
// At least 12 bytes should remain now
|
||||
if (data.size() < 9|| data[0] != 1 || data[2] != 4)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol",
|
||||
"A message notifying an accepted connection wasn't "
|
||||
"formated as expected.");
|
||||
return;
|
||||
}
|
||||
STKPeer* peer = event->getPeer();
|
||||
|
||||
// Accepted
|
||||
@@ -405,9 +385,10 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
|
||||
name = PlayerManager::getCurrentOnlineUserName();
|
||||
else
|
||||
name = PlayerManager::getCurrentPlayer()->getName();
|
||||
uint8_t my_player_id = data.getUInt8(1);
|
||||
uint8_t my_host_id = data.getUInt8(7);
|
||||
uint8_t authorised = data.getUInt8(8);
|
||||
uint8_t my_player_id = data[0];
|
||||
uint8_t my_host_id = data[1];
|
||||
uint8_t authorised = data[2];
|
||||
data.removeFront(3);
|
||||
// Store this client's authorisation status in the peer information
|
||||
// for the server.
|
||||
event->getPeer()->setAuthorised(authorised!=0);
|
||||
@@ -418,31 +399,26 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
|
||||
STKHost::get()->getGameSetup()->setLocalMaster(my_player_id);
|
||||
m_setup->setNumLocalPlayers(1);
|
||||
// connection token
|
||||
uint32_t token = data.gui32(3);
|
||||
uint32_t token = data.getToken();
|
||||
peer->setClientServerToken(token);
|
||||
|
||||
// Add all players
|
||||
// ===============
|
||||
int n = 9;
|
||||
while (n < data.size())
|
||||
while (data.size() > 0)
|
||||
{
|
||||
if (data[n] != 1 )
|
||||
Log::error("ClientLobbyRoomProtocol",
|
||||
"Bad format in players list.");
|
||||
|
||||
uint8_t player_id = data[n + 1];
|
||||
uint8_t player_id = data[0];
|
||||
uint8_t host_id = data[1];
|
||||
irr::core::stringw name;
|
||||
int bytes_read = data.decodeStringW(n + 2, &name);
|
||||
uint8_t host_id = data.getUInt8(n+2+bytes_read);
|
||||
|
||||
int bytes_read = data.decodeStringW(2, &name);
|
||||
|
||||
NetworkPlayerProfile* profile2 =
|
||||
new NetworkPlayerProfile(player_id, name);
|
||||
profile2->setHostId(host_id);
|
||||
m_setup->addPlayer(profile2);
|
||||
n += bytes_read+3;
|
||||
// Inform the network lobby of all players so that the GUI can
|
||||
// show all currently connected players.
|
||||
NetworkingLobby::getInstance()->addPlayer(profile2);
|
||||
data.removeFront(bytes_read+2);
|
||||
}
|
||||
|
||||
// Add self after other players so that player order is identical
|
||||
@@ -459,24 +435,18 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2
|
||||
* --------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | 1 | refusal code |
|
||||
* --------------------
|
||||
* Byte 0
|
||||
* ----------------
|
||||
* Size | 1 |
|
||||
* Data | refusal code |
|
||||
* ----------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::connectionRefused(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 1)) return;
|
||||
const NetworkString &data = event->data();
|
||||
if (data.size() != 2 || data[0] != 1) // 2 bytes remains now
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol",
|
||||
"A message notifying a refused connection wasn't formated "
|
||||
"as expected.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (data[1]) // the second byte
|
||||
|
||||
switch (data[0]) // the second byte
|
||||
{
|
||||
case 0:
|
||||
Log::info("ClientLobbyRoomProtocol",
|
||||
@@ -500,24 +470,19 @@ void ClientLobbyRoomProtocol::connectionRefused(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2
|
||||
* --------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | 1 | refusal code |
|
||||
* --------------------
|
||||
* Byte 0
|
||||
* ----------------
|
||||
* Size | 1 |
|
||||
* Data | refusal code |
|
||||
* ----------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event)
|
||||
{
|
||||
const NetworkString &data = event->data();
|
||||
if (data.size() != 2 || data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol",
|
||||
"A message notifying a refused kart selection wasn't "
|
||||
"formated as expected.");
|
||||
return;
|
||||
}
|
||||
if(!checkDataSize(event, 1)) return;
|
||||
|
||||
switch (data[1]) // the error code
|
||||
const NetworkString &data = event->data();
|
||||
|
||||
switch (data[0]) // the error code
|
||||
{
|
||||
case 0:
|
||||
Log::info("ClientLobbyRoomProtocol",
|
||||
@@ -539,25 +504,19 @@ void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2 3 N+3
|
||||
* Byte 0 1 2 3 N+3
|
||||
* --------------------------------------------------
|
||||
* Size | 1 | 1 | 1 | N |
|
||||
* Data | 1 | player id | N (kart name size) | kart name |
|
||||
* Size | 1 | 1 | N |
|
||||
* Data | player id | N (kart name size) | kart name |
|
||||
* --------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::kartSelectionUpdate(Event* event)
|
||||
{
|
||||
if(!checkDataSize(event, 3)) return;
|
||||
const NetworkString &data = event->data();
|
||||
if (data.size() < 3 || data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol",
|
||||
"A message notifying a kart selection update wasn't "
|
||||
"formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint8_t player_id = data[1];
|
||||
uint8_t player_id = data[0];
|
||||
std::string kart_name;
|
||||
data.decodeString(2, &kart_name);
|
||||
data.decodeString(1, &kart_name);
|
||||
if (!m_setup->isKartAvailable(kart_name))
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol",
|
||||
@@ -571,67 +530,28 @@ void ClientLobbyRoomProtocol::kartSelectionUpdate(Event* event)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \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 |
|
||||
* -------------
|
||||
* \param event : Event providing the information (no additional information
|
||||
* in this case).
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::startGame(Event* event)
|
||||
{
|
||||
const NetworkString &data = event->data();
|
||||
if (data.size() < 5 || data[0] != 4)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
|
||||
"selection update wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint32_t token = data.gui32(1);
|
||||
if (token == STKHost::get()->getPeers()[0]->getClientServerToken())
|
||||
{
|
||||
m_state = PLAYING;
|
||||
ProtocolManager::getInstance()
|
||||
->requestStart(new StartGameProtocol(m_setup));
|
||||
Log::error("ClientLobbyRoomProtocol", "Starting new game");
|
||||
}
|
||||
else
|
||||
Log::error("ClientLobbyRoomProtocol", "Bad token when starting game");
|
||||
|
||||
m_state = PLAYING;
|
||||
ProtocolManager::getInstance()
|
||||
->requestStart(new StartGameProtocol(m_setup));
|
||||
Log::error("ClientLobbyRoomProtocol", "Starting new game");
|
||||
} // startGame
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \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 |
|
||||
* -------------
|
||||
* \param event : Event providing the information (no additional information
|
||||
* in this case).
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::startSelection(Event* event)
|
||||
{
|
||||
const NetworkString &data = event->data();
|
||||
if (data.size() < 5 || data[0] != 4)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
|
||||
"selection update wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint32_t token = data.gui32(1);
|
||||
if (token == STKHost::get()->getPeers()[0]->getClientServerToken())
|
||||
{
|
||||
m_state = KART_SELECTION;
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart selection starts now");
|
||||
}
|
||||
else
|
||||
Log::error("ClientLobbyRoomProtocol", "Bad token");
|
||||
|
||||
m_state = KART_SELECTION;
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart selection starts now");
|
||||
} // startSelection
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -640,26 +560,17 @@ void ClientLobbyRoomProtocol::startSelection(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7 8 9
|
||||
* ---------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 | |
|
||||
* Data | 4 | token | 1 | Kart 1 ID | 1 | kart id 2 | ... |
|
||||
* ---------------------------------------------------
|
||||
* Byte 0 1
|
||||
* -------------------------------
|
||||
* Size | 1 | 1 | |
|
||||
* Data | Kart 1 ID | kart id 2 | ... |
|
||||
* -------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::raceFinished(Event* event)
|
||||
{
|
||||
if(!checkDataSize(event, 1)) return;
|
||||
|
||||
NetworkString &data = event->data();
|
||||
if (data.size() < 5)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "Not enough data provided.");
|
||||
return;
|
||||
}
|
||||
if (event->getPeer()->getClientServerToken() != data.gui32(1))
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "Bad token");
|
||||
return;
|
||||
}
|
||||
data.removeFront(5);
|
||||
Log::error("ClientLobbyRoomProtocol",
|
||||
"Server notified that the race is finished.");
|
||||
|
||||
@@ -695,21 +606,11 @@ void ClientLobbyRoomProtocol::raceFinished(Event* event)
|
||||
int position = 1;
|
||||
while(data.size()>0)
|
||||
{
|
||||
if (data.size() < 2)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "Incomplete field.");
|
||||
return;
|
||||
}
|
||||
if (data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "Badly formatted field.");
|
||||
return;
|
||||
}
|
||||
uint8_t kart_id = data[1];
|
||||
uint8_t kart_id = data[0];
|
||||
ranked_world->setKartPosition(kart_id,position);
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart %d has finished #%d",
|
||||
kart_id, position);
|
||||
data.removeFront(2);
|
||||
data.removeFront(1);
|
||||
position++;
|
||||
}
|
||||
ranked_world->endSetKartPositions();
|
||||
@@ -723,22 +624,18 @@ void ClientLobbyRoomProtocol::raceFinished(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7 8 9
|
||||
* --------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | player id | 1 | major mode vote |
|
||||
* --------------------------------------------------------
|
||||
* Byte 0 1 2
|
||||
* ------------------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data |player id | major mode vote |
|
||||
* ------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerMajorVote(Event* event)
|
||||
{
|
||||
const NetworkString &data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 9))
|
||||
if (!checkDataSize(event, 2))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 4))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerMajorVote(data[6], data[8]);
|
||||
m_setup->getRaceConfig()->setPlayerMajorVote(data[0], data[1]);
|
||||
} // playerMajorVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -746,22 +643,17 @@ void ClientLobbyRoomProtocol::playerMajorVote(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7 8 9
|
||||
* ----------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | player id | 1 | races count |
|
||||
* ----------------------------------------------------
|
||||
* Byte 0 1
|
||||
* ---------------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | player id | races count |
|
||||
* ---------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerRaceCountVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 2)) return;
|
||||
const NetworkString &data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 9))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 1))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerRaceCountVote(data[6], data[8]);
|
||||
m_setup->getRaceConfig()->setPlayerRaceCountVote(data[0], data[1]);
|
||||
} // playerRaceCountVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -769,22 +661,17 @@ void ClientLobbyRoomProtocol::playerRaceCountVote(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7 8 9
|
||||
* --------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 4 |
|
||||
* Data | 4 | priv token | 1 | player id | 4 | minor mode vote |
|
||||
* --------------------------------------------------------
|
||||
* Byte 0 1
|
||||
* -------------------------------
|
||||
* Size | 1 | 4 |
|
||||
* Data | player id | minor mode vote |
|
||||
* -------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerMinorVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 2)) return;
|
||||
const NetworkString &data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 9))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 4))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerMinorVote(data[6], data[8]);
|
||||
m_setup->getRaceConfig()->setPlayerMinorVote(data[0], data[1]);
|
||||
} // playerMinorVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -793,25 +680,20 @@ void ClientLobbyRoomProtocol::playerMinorVote(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7 8 N+8 N+9 N+10
|
||||
* ---------------------------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | N | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | player id | N | track name | 1 | track number (gp) |
|
||||
* ---------------------------------------------------------------------------
|
||||
* Byte 0 1 2 3
|
||||
* --------------------------------------------------
|
||||
* Size | 1 | 1 | 1 | N |
|
||||
* Data | player id | track number (gp) | N | track name |
|
||||
* --------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerTrackVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 3)) return;
|
||||
const NetworkString &data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 10))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
std::string track_name;
|
||||
int N = data.decodeString(7, &track_name);
|
||||
if (!isByteCorrect(event, N+7, 1))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerTrackVote(data[6], track_name,
|
||||
data[N+8]);
|
||||
int N = data.decodeString(2, &track_name);
|
||||
m_setup->getRaceConfig()->setPlayerTrackVote(data[0], track_name,
|
||||
data[1]);
|
||||
} // playerTrackVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -820,24 +702,18 @@ void ClientLobbyRoomProtocol::playerTrackVote(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7 8 9 10 11
|
||||
* -------------------------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | player id | 1 | reversed | 1 | track number (gp) |
|
||||
* -------------------------------------------------------------------------
|
||||
* Byte 0 1 2
|
||||
* -------------------------------------------
|
||||
* Size | 1 | 1 | 1 |
|
||||
* Data | player id |reversed | track number (gp) |
|
||||
* -------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerReversedVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 3)) return;
|
||||
const NetworkString &data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 11))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 9, 1))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerReversedVote(data[6], data[8]!=0, data[10]);
|
||||
m_setup->getRaceConfig()->setPlayerReversedVote(data[0], data[1]!=0,
|
||||
data[2]);
|
||||
} // playerReversedVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -846,22 +722,17 @@ void ClientLobbyRoomProtocol::playerReversedVote(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7 8 9 10 11
|
||||
* ---------------------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | player id | 1 | laps | 1 | track number (gp) |
|
||||
* ---------------------------------------------------------------------
|
||||
* Byte 0 1 2
|
||||
* ----------------------------------------
|
||||
* Size | 1 | 1 | 1 |
|
||||
* Data | player id | laps | track number (gp) |
|
||||
* ----------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::playerLapsVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 3)) return;
|
||||
const NetworkString &data = event->data();
|
||||
if (!checkDataSizeAndToken(event, 9))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 1))
|
||||
return;
|
||||
m_setup->getRaceConfig()->setPlayerLapsVote(data[6], data[8], data[10]);
|
||||
m_setup->getRaceConfig()->setPlayerLapsVote(data[0], data[1], data[2]);
|
||||
} // playerLapsVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -141,14 +141,14 @@ void ConnectToPeer::asynchronousUpdate()
|
||||
else
|
||||
broadcast_address.copy(m_peer_address);
|
||||
|
||||
char data[] = "aloha_stk\0";
|
||||
STKHost::get()->sendRawPacket((uint8_t*)(data), 10, broadcast_address);
|
||||
BareNetworkString aloha(std::string("aloha_stk"));
|
||||
STKHost::get()->sendRawPacket(aloha, broadcast_address);
|
||||
Log::info("ConnectToPeer", "Broadcast aloha sent.");
|
||||
StkTime::sleep(1);
|
||||
|
||||
broadcast_address.setIP(0x7f000001); // 127.0.0.1 (localhost)
|
||||
broadcast_address.setPort(m_peer_address.getPort());
|
||||
STKHost::get()->sendRawPacket((uint8_t*)(data), 10, broadcast_address);
|
||||
STKHost::get()->sendRawPacket(aloha, broadcast_address);
|
||||
Log::info("ConnectToPeer", "Broadcast aloha to self.");
|
||||
m_state = CONNECTING;
|
||||
break;
|
||||
|
||||
@@ -377,10 +377,19 @@ void ConnectToServer::handleSameLAN()
|
||||
const int LEN=256;
|
||||
char buffer[LEN];
|
||||
int len = host->receiveRawPacket(buffer, LEN, &sender, 2000);
|
||||
if(len<0)
|
||||
{
|
||||
Log::warn("ConnectToServer",
|
||||
"Received invalid server information message.");
|
||||
return;
|
||||
}
|
||||
|
||||
BareNetworkString message(buffer, len);
|
||||
std::string received;
|
||||
message.decodeString(0, &received);
|
||||
host->startListening(); // start listening again
|
||||
const char data[] = "aloha_stk\0";
|
||||
if (strcmp(data, buffer) == 0)
|
||||
std::string aloha("aloha_stk");
|
||||
if (received==aloha)
|
||||
{
|
||||
Log::info("ConnectToServer", "LAN Server found : %s",
|
||||
sender.toString().c_str());
|
||||
|
||||
@@ -58,7 +58,7 @@ bool ControllerEventsProtocol::notifyEventAsynchronous(Event* event)
|
||||
data.size());
|
||||
return true;
|
||||
}
|
||||
uint32_t token = data.gui32();
|
||||
uint32_t token = data.getUInt32();
|
||||
NetworkString pure_message = data;
|
||||
pure_message.removeFront(4);
|
||||
if (token != event->getPeer()->getClientServerToken())
|
||||
@@ -80,9 +80,9 @@ bool ControllerEventsProtocol::notifyEventAsynchronous(Event* event)
|
||||
kart_id);
|
||||
return true;
|
||||
}
|
||||
uint8_t serialized_1 = ns.gui8(1);
|
||||
PlayerAction action = (PlayerAction)(ns.gui8(4));
|
||||
int action_value = ns.gui32(5);
|
||||
uint8_t serialized_1 = ns.getUInt8(1);
|
||||
PlayerAction action = (PlayerAction)(ns.getUInt8(4));
|
||||
int action_value = ns.getUInt32(5);
|
||||
Controller *controller = World::getWorld()->getKart(kart_id)
|
||||
->getController();
|
||||
KartControl *controls = controller->getControls();
|
||||
@@ -105,21 +105,9 @@ bool ControllerEventsProtocol::notifyEventAsynchronous(Event* event)
|
||||
}
|
||||
if (NetworkConfig::get()->isServer())
|
||||
{
|
||||
const std::vector<STKPeer*> &peers = STKHost::get()->getPeers();
|
||||
for(unsigned int i=0; i<peers.size(); i++)
|
||||
{
|
||||
STKPeer *peer = peers[i];
|
||||
// Don't send message to the host from which the message
|
||||
// was sent from originally
|
||||
if(peer != event->getPeer())
|
||||
{
|
||||
NetworkString ns2(4+pure_message.size());
|
||||
ns2.ai32(peer->getClientServerToken());
|
||||
ns2 += pure_message;
|
||||
ProtocolManager::getInstance()->sendMessage(this, peer,
|
||||
ns2, false);
|
||||
} // if peer != event->getPeer()
|
||||
} // for i in peers
|
||||
// Send update to all clients except the original sender.
|
||||
STKHost::get()->sendPacketExcept(event->getPeer(),
|
||||
&pure_message, false);
|
||||
} // if server
|
||||
return true;
|
||||
} // notifyEventAsynchronous
|
||||
@@ -159,14 +147,12 @@ void ControllerEventsProtocol::controllerAction(Controller* controller,
|
||||
uint8_t serialized_2 = (uint8_t)(controls->m_accel*255.0);
|
||||
uint8_t serialized_3 = (uint8_t)(controls->m_steer*127.0);
|
||||
|
||||
NetworkString ns(17);
|
||||
uint32_t token = STKHost::get()->getPeers()[0]->getClientServerToken();
|
||||
ns.ai32(token);
|
||||
ns.af(World::getWorld()->getTime());
|
||||
ns.addUInt8(controller->getKart()->getWorldKartId());
|
||||
ns.ai8(serialized_1).ai8(serialized_2).ai8(serialized_3);
|
||||
ns.ai8((uint8_t)(action)).ai32(value);
|
||||
NetworkString *ns = getNetworkString(17);
|
||||
ns->addFloat(World::getWorld()->getTime());
|
||||
ns->addUInt8(controller->getKart()->getWorldKartId());
|
||||
ns->addUInt8(serialized_1).addUInt8(serialized_2).addUInt8(serialized_3);
|
||||
ns->addUInt8((uint8_t)(action)).addUInt32(value);
|
||||
|
||||
Log::info("ControllerEventsProtocol", "Action %d value %d", action, value);
|
||||
sendMessage(ns, false); // send message to server
|
||||
sendToServer(ns, false); // send message to server
|
||||
} // controllerAction
|
||||
|
||||
@@ -44,12 +44,12 @@ bool GameEventsProtocol::notifyEvent(Event* event)
|
||||
Log::warn("GameEventsProtocol", "Too short message.");
|
||||
return true;
|
||||
}
|
||||
if ( event->getPeer()->getClientServerToken() != data.gui32())
|
||||
if ( event->getPeer()->getClientServerToken() != data.getUInt32())
|
||||
{
|
||||
Log::warn("GameEventsProtocol", "Bad token.");
|
||||
return true;
|
||||
}
|
||||
int8_t type = data.gui8(4);
|
||||
int8_t type = data.getUInt8(4);
|
||||
data.removeFront(5);
|
||||
switch (type)
|
||||
{
|
||||
@@ -85,8 +85,8 @@ void GameEventsProtocol::collectedItem(Item* item, AbstractKart* kart)
|
||||
const std::vector<STKPeer*> &peers = STKHost::get()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString ns(11);
|
||||
ns.ai32(peers[i]->getClientServerToken());
|
||||
NetworkString *ns = getNetworkString(7);
|
||||
ns->setSynchronous(true);
|
||||
// Item picked : send item id, powerup type and kart race id
|
||||
uint8_t powerup = 0;
|
||||
if (item->getType() == Item::ITEM_BANANA)
|
||||
@@ -95,11 +95,10 @@ void GameEventsProtocol::collectedItem(Item* item, AbstractKart* kart)
|
||||
powerup = (((int)(kart->getPowerup()->getType()) << 4) & 0xf0)
|
||||
+ (kart->getPowerup()->getNum() & 0x0f);
|
||||
|
||||
ns.ai8(GE_ITEM_COLLECTED).ai32(item->getItemId()).ai8(powerup)
|
||||
.ai8(kart->getWorldKartId());
|
||||
ProtocolManager::getInstance()->sendMessage(this, peers[i], ns,
|
||||
/*reliable*/true,
|
||||
/*synchronous*/true);
|
||||
ns->addUInt8(GE_ITEM_COLLECTED).addUInt32(item->getItemId())
|
||||
.addUInt8(powerup).addUInt8(kart->getWorldKartId());
|
||||
peers[i]->sendPacket(ns, /*reliable*/true);
|
||||
delete ns;
|
||||
Log::info("GameEventsProtocol",
|
||||
"Notified a peer that a kart collected item %d.",
|
||||
(int)(kart->getPowerup()->getType()));
|
||||
@@ -115,9 +114,9 @@ void GameEventsProtocol::collectedItem(const NetworkString &data)
|
||||
{
|
||||
Log::warn("GameEventsProtocol", "Too short message.");
|
||||
}
|
||||
uint32_t item_id = data.gui32();
|
||||
uint8_t powerup_type = data.gui8(4);
|
||||
uint8_t kart_id = data.gui8(5);
|
||||
uint32_t item_id = data.getUInt32();
|
||||
uint8_t powerup_type = data.getUInt8(4);
|
||||
uint8_t kart_id = data.getUInt8(5);
|
||||
// now set the kart powerup
|
||||
AbstractKart* kart = World::getWorld()->getKart(kart_id);
|
||||
ItemManager::get()->collectedItem(ItemManager::get()->getItem(item_id),
|
||||
@@ -134,19 +133,12 @@ void GameEventsProtocol::collectedItem(const NetworkString &data)
|
||||
*/
|
||||
void GameEventsProtocol::kartFinishedRace(AbstractKart *kart, float time)
|
||||
{
|
||||
NetworkString ns(20);
|
||||
|
||||
const std::vector<STKPeer*> &peers = STKHost::get()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
ns.addUInt32(peers[i]->getClientServerToken())
|
||||
.addUInt8(GE_KART_FINISHED_RACE)
|
||||
.addUInt8(kart->getWorldKartId()).addFloat(time);
|
||||
|
||||
ProtocolManager::getInstance()->sendMessage(this, peers[i], ns,
|
||||
/*reliable*/true,
|
||||
/*synchronous*/true);
|
||||
} // for i in peers
|
||||
NetworkString *ns = getNetworkString(20);
|
||||
ns->setSynchronous(true);
|
||||
ns->addUInt8(GE_KART_FINISHED_RACE).addUInt8(kart->getWorldKartId())
|
||||
.addFloat(time);
|
||||
sendMessageToPeersChangingToken(ns, /*reliable*/true);
|
||||
delete ns;
|
||||
} // kartFinishedRace
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "config/user_config.hpp"
|
||||
#include "network/network.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
@@ -89,14 +90,14 @@ void GetPublicAddress::createStunRequest()
|
||||
m_transaction_host = new Network(1, 1, 0, 0);
|
||||
|
||||
// Assemble the message for the stun server
|
||||
NetworkString s(21);
|
||||
BareNetworkString s(21);
|
||||
|
||||
// bytes 0-1: the type of the message
|
||||
// bytes 2-3: message length added to header (attributes)
|
||||
uint16_t message_type = 0x0001; // binding request
|
||||
uint16_t message_length = 0x0000;
|
||||
s.addUInt16(message_type).addUInt16(message_length)
|
||||
.addInt(0x2112A442);
|
||||
.addUInt32(0x2112A442);
|
||||
// bytes 8-19: the transaction id
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
@@ -107,7 +108,7 @@ void GetPublicAddress::createStunRequest()
|
||||
s.addChar(0);
|
||||
|
||||
|
||||
m_transaction_host->sendRawPacket(s.getBytes(), 20,
|
||||
m_transaction_host->sendRawPacket(s,
|
||||
TransportAddress(m_stun_server_ip,
|
||||
m_stun_server_port) );
|
||||
freeaddrinfo(res);
|
||||
@@ -139,7 +140,7 @@ std::string GetPublicAddress::parseStunResponse()
|
||||
return "STUN response contains no data at all";
|
||||
|
||||
// Convert to network string.
|
||||
NetworkString datas(std::string(buffer, len));
|
||||
NetworkString datas((uint8_t*)buffer, len);
|
||||
|
||||
// check that the stun response is a response, contains the magic cookie
|
||||
// and the transaction ID
|
||||
|
||||
@@ -48,9 +48,8 @@ bool KartUpdateProtocol::notifyEvent(Event* event)
|
||||
while(ns.size() >= 29)
|
||||
{
|
||||
uint8_t kart_id = ns.getUInt8(0);
|
||||
Vec3 xyz;
|
||||
btQuaternion quat;
|
||||
ns.get(&xyz, 1).get(&quat, 13);
|
||||
Vec3 xyz = ns.getVec3(1);
|
||||
btQuaternion quat = ns.getQuat(13);
|
||||
m_next_positions [kart_id] = xyz;
|
||||
m_next_quaternions[kart_id] = quat;
|
||||
ns.removeFront(29);
|
||||
@@ -81,35 +80,40 @@ void KartUpdateProtocol::update()
|
||||
if (NetworkConfig::get()->isServer())
|
||||
{
|
||||
World *world = World::getWorld();
|
||||
NetworkString ns(4+world->getNumKarts()*29);
|
||||
ns.af( world->getTime() );
|
||||
NetworkString *ns = getNetworkString(4+world->getNumKarts()*29);
|
||||
ns->setSynchronous(true);
|
||||
ns->addFloat( world->getTime() );
|
||||
for (unsigned int i = 0; i < world->getNumKarts(); i++)
|
||||
{
|
||||
AbstractKart* kart = world->getKart(i);
|
||||
Vec3 xyz = kart->getXYZ();
|
||||
ns.addUInt8( kart->getWorldKartId());
|
||||
ns.add(xyz).add(kart->getRotation());
|
||||
ns->addUInt8( kart->getWorldKartId());
|
||||
ns->add(xyz).add(kart->getRotation());
|
||||
Log::verbose("KartUpdateProtocol",
|
||||
"Sending %d's positions %f %f %f",
|
||||
kart->getWorldKartId(), xyz[0], xyz[1], xyz[2]);
|
||||
}
|
||||
sendSynchronousMessage(ns, false);
|
||||
sendMessageToPeersChangingToken(ns, /*reliable*/false);
|
||||
delete ns;
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkString ns(4+29*race_manager->getNumLocalPlayers());
|
||||
ns.af(World::getWorld()->getTime());
|
||||
NetworkString *ns =
|
||||
getNetworkString(4+29*race_manager->getNumLocalPlayers());
|
||||
ns->setSynchronous(true);
|
||||
ns->addFloat(World::getWorld()->getTime());
|
||||
for(unsigned int i=0; i<race_manager->getNumLocalPlayers(); i++)
|
||||
{
|
||||
AbstractKart *kart = World::getWorld()->getLocalPlayerKart(i);
|
||||
const Vec3 &xyz = kart->getXYZ();
|
||||
ns.addUInt8(kart->getWorldKartId());
|
||||
ns.add(xyz).add(kart->getRotation());
|
||||
ns->addUInt8(kart->getWorldKartId());
|
||||
ns->add(xyz).add(kart->getRotation());
|
||||
Log::verbose("KartUpdateProtocol",
|
||||
"Sending %d's positions %f %f %f",
|
||||
kart->getWorldKartId(), xyz[0], xyz[1], xyz[2]);
|
||||
}
|
||||
sendSynchronousMessage(ns, false);
|
||||
sendToServer(ns, /*reliable*/false);
|
||||
delete ns;
|
||||
} // if server
|
||||
} // if (current_time > time + 0.1)
|
||||
|
||||
|
||||
@@ -50,8 +50,9 @@ void PingProtocol::asynchronousUpdate()
|
||||
if (StkTime::getRealTime() > m_last_ping_time+m_delay_between_pings)
|
||||
{
|
||||
m_last_ping_time = StkTime::getRealTime();
|
||||
uint8_t data = 0;
|
||||
STKHost::get()->sendRawPacket(&data, 1, m_ping_dst);
|
||||
BareNetworkString data;
|
||||
data.addUInt8(0);
|
||||
STKHost::get()->sendRawPacket(data, m_ping_dst);
|
||||
Log::info("PingProtocol", "Ping message sent");
|
||||
}
|
||||
} // asynchronousUpdate
|
||||
|
||||
@@ -79,9 +79,8 @@ void RequestConnection::asynchronousUpdate()
|
||||
{
|
||||
const Server *server =
|
||||
ServersManager::get()->getServerByID(m_server_id);
|
||||
NetworkString s(std::string("connection-request"));
|
||||
STKHost::get()->sendRawPacket(s.getBytes(), s.size(),
|
||||
server->getAddress());
|
||||
BareNetworkString message(std::string("connection-request"));
|
||||
STKHost::get()->sendRawPacket(message, server->getAddress());
|
||||
m_state = DONE;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -78,11 +78,11 @@ bool ServerLobbyRoomProtocol::notifyEventAsynchronous(Event* event)
|
||||
assert(m_setup); // assert that the setup exists
|
||||
if (event->getType() == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
const NetworkString &data = event->data();
|
||||
NetworkString &data = event->data();
|
||||
assert(data.size()); // message not empty
|
||||
uint8_t message_type;
|
||||
message_type = data[0];
|
||||
event->removeFront(1);
|
||||
data.removeFront(1);
|
||||
Log::info("ServerLobbyRoomProtocol", "Message received with type %d.",
|
||||
message_type);
|
||||
switch(message_type)
|
||||
@@ -224,12 +224,10 @@ void ServerLobbyRoomProtocol::registerServer()
|
||||
void ServerLobbyRoomProtocol::startGame()
|
||||
{
|
||||
const std::vector<STKPeer*> &peers = STKHost::get()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString ns(6);
|
||||
ns.ai8(LE_START_RACE).ai8(4).ai32(peers[i]->getClientServerToken());
|
||||
sendMessage(peers[i], ns, true); // reliably
|
||||
}
|
||||
NetworkString *ns = getNetworkString(1);
|
||||
ns->addUInt8(LE_START_RACE);
|
||||
sendMessageToPeersChangingToken(ns, /*reliable*/true);
|
||||
delete ns;
|
||||
Protocol *p = new StartGameProtocol(m_setup);
|
||||
p->requestStart();
|
||||
m_in_race = true;
|
||||
@@ -249,13 +247,12 @@ void ServerLobbyRoomProtocol::startSelection(const Event *event)
|
||||
return;
|
||||
}
|
||||
const std::vector<STKPeer*> &peers = STKHost::get()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString ns(6);
|
||||
// start selection
|
||||
ns.ai8(LE_START_SELECTION).ai8(4).ai32(peers[i]->getClientServerToken());
|
||||
sendMessage(peers[i], ns, true); // reliably
|
||||
}
|
||||
NetworkString *ns = getNetworkString(1);
|
||||
// start selection
|
||||
ns->addUInt8(LE_START_SELECTION);
|
||||
sendMessageToPeersChangingToken(ns, /*reliable*/true);
|
||||
delete ns;
|
||||
|
||||
m_selection_enabled = true;
|
||||
|
||||
m_state = SELECTING_KARTS;
|
||||
@@ -338,20 +335,17 @@ void ServerLobbyRoomProtocol::checkRaceFinished()
|
||||
|
||||
const std::vector<STKPeer*> &peers = STKHost::get()->getPeers();
|
||||
|
||||
NetworkString queue(karts_results.size()*2);
|
||||
NetworkString *total = getNetworkString(1+karts_results.size());
|
||||
total->setSynchronous(true);
|
||||
total->addUInt8(LE_RACE_FINISHED);
|
||||
for (unsigned int i = 0; i < karts_results.size(); i++)
|
||||
{
|
||||
queue.ai8(1).ai8(karts_results[i]); // kart pos = i+1
|
||||
total->addUInt8(karts_results[i]); // kart pos = i+1
|
||||
Log::info("ServerLobbyRoomProtocol", "Kart %d finished #%d",
|
||||
karts_results[i], i + 1);
|
||||
}
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString ns(6);
|
||||
ns.ai8(LE_RACE_FINISHED).ai8(4).ai32(peers[i]->getClientServerToken());
|
||||
NetworkString total = ns + queue;
|
||||
sendSynchronousMessage(peers[i], total, true);
|
||||
}
|
||||
sendMessageToPeersChangingToken(total, /*reliable*/ true);
|
||||
delete total;
|
||||
Log::info("ServerLobbyRoomProtocol", "End of game message sent");
|
||||
m_in_race = false;
|
||||
|
||||
@@ -395,10 +389,11 @@ void ServerLobbyRoomProtocol::kartDisconnected(Event* event)
|
||||
STKPeer* peer = event->getPeer();
|
||||
if (peer->getPlayerProfile() != NULL) // others knew him
|
||||
{
|
||||
NetworkString msg(3);
|
||||
msg.ai8(LE_PLAYER_DISCONNECTED).ai8(1)
|
||||
.ai8(peer->getPlayerProfile()->getGlobalPlayerId());
|
||||
sendMessage(msg);
|
||||
NetworkString *msg = getNetworkString(2);
|
||||
msg->addUInt8(LE_PLAYER_DISCONNECTED)
|
||||
.addUInt8(peer->getPlayerProfile()->getGlobalPlayerId());
|
||||
sendMessageToPeersChangingToken(msg, /*reliable*/true);
|
||||
delete msg;
|
||||
Log::info("ServerLobbyRoomProtocol", "Player disconnected : id %d",
|
||||
peer->getPlayerProfile()->getGlobalPlayerId());
|
||||
m_setup->removePlayer(peer->getPlayerProfile());
|
||||
@@ -431,13 +426,14 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
|
||||
if (m_setup->getPlayerCount() >= NetworkConfig::get()->getMaxPlayers() ||
|
||||
m_state!=ACCEPTING_CLIENTS )
|
||||
{
|
||||
NetworkString message(3);
|
||||
NetworkString *message = getNetworkString(2);
|
||||
// Len, error code: 2 = busy, 0 = too many players
|
||||
message.ai8(LE_CONNECTION_REFUSED).ai8(1)
|
||||
.ai8(m_state!=ACCEPTING_CLIENTS ? 2 : 0);
|
||||
message->addUInt8(LE_CONNECTION_REFUSED)
|
||||
.addUInt8(m_state!=ACCEPTING_CLIENTS ? 2 : 0);
|
||||
|
||||
// send only to the peer that made the request
|
||||
sendMessage(peer, message);
|
||||
peer->sendPacket(message);
|
||||
delete message;
|
||||
Log::verbose("ServerLobbyRoomProtocol", "Player refused");
|
||||
return;
|
||||
}
|
||||
@@ -465,11 +461,12 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
|
||||
|
||||
// Notify everybody that there is a new player
|
||||
// -------------------------------------------
|
||||
NetworkString message(8);
|
||||
NetworkString *message = getNetworkString(3+1+name_u8.size());
|
||||
// size of id -- id -- size of local id -- local id;
|
||||
message.ai8(LE_NEW_PLAYER_CONNECTED).ai8(1).ai8(new_player_id)
|
||||
.encodeString(name_u8).addUInt8(new_host_id);
|
||||
ProtocolManager::getInstance()->sendMessageExcept(this, peer, message);
|
||||
message->addUInt8(LE_NEW_PLAYER_CONNECTED).addUInt8(new_player_id)
|
||||
.addUInt8(new_host_id).encodeString(name_u8);
|
||||
STKHost::get()->sendPacketExcept(peer, message);
|
||||
delete message;
|
||||
|
||||
// Now answer to the peer that just connected
|
||||
// ------------------------------------------
|
||||
@@ -480,28 +477,30 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
|
||||
(token_generator.get(RAND_MAX) & 0xff) << 8 |
|
||||
(token_generator.get(RAND_MAX) & 0xff));
|
||||
|
||||
peer->setClientServerToken(token);
|
||||
|
||||
const std::vector<NetworkPlayerProfile*> &players = m_setup->getPlayers();
|
||||
// send a message to the one that asked to connect
|
||||
// Size is overestimated, probably one player's data will not be sent
|
||||
NetworkString message_ack(14 + players.size() * 7);
|
||||
// Estimate 10 as average name length
|
||||
NetworkString *message_ack = getNetworkString(4 + players.size() * (2+10));
|
||||
// connection success -- size of token -- token
|
||||
message_ack.ai8(LE_CONNECTION_ACCEPTED).ai8(1).ai8(new_player_id).ai8(4)
|
||||
.ai32(token).addUInt8(new_host_id).addUInt8(is_authorised);
|
||||
message_ack->addUInt8(LE_CONNECTION_ACCEPTED).addUInt8(new_player_id)
|
||||
.addUInt8(new_host_id).addUInt8(is_authorised);
|
||||
// Add all players so that this user knows (this new player is only added
|
||||
// to the list of players later, so the new player's info is not included)
|
||||
for (unsigned int i = 0; i < players.size(); i++)
|
||||
{
|
||||
message_ack.ai8(1).ai8(players[i]->getGlobalPlayerId())
|
||||
.encodeString(players[i]->getName())
|
||||
.addUInt8(players[i]->getHostId());
|
||||
message_ack->addUInt8(players[i]->getGlobalPlayerId())
|
||||
.addUInt8(players[i]->getHostId())
|
||||
.encodeString(players[i]->getName());
|
||||
}
|
||||
sendMessage(peer, message_ack);
|
||||
peer->sendPacket(message_ack);
|
||||
delete message_ack;
|
||||
|
||||
NetworkPlayerProfile* profile = new NetworkPlayerProfile(new_player_id, name);
|
||||
profile->setHostId(new_host_id);
|
||||
m_setup->addPlayer(profile);
|
||||
peer->setPlayerProfile(profile);
|
||||
peer->setClientServerToken(token);
|
||||
peer->setAuthorised(is_authorised);
|
||||
peer->setHostId(new_host_id);
|
||||
|
||||
@@ -515,11 +514,11 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
|
||||
* \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 |
|
||||
* ---------------------------------------------------
|
||||
* Byte 0 1
|
||||
* ----------------------------------
|
||||
* Size | 1 | N |
|
||||
* Data | N (kart name size) | kart name |
|
||||
* ----------------------------------
|
||||
*/
|
||||
void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
|
||||
{
|
||||
@@ -530,48 +529,54 @@ void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkDataSize(event, 1)) return;
|
||||
|
||||
const NetworkString &data = event->data();
|
||||
STKPeer* peer = event->getPeer();
|
||||
if (!checkDataSizeAndToken(event, 6))
|
||||
return;
|
||||
|
||||
std::string kart_name;
|
||||
data.decodeString(5, &kart_name);
|
||||
data.decodeString(0, &kart_name);
|
||||
// check if selection is possible
|
||||
if (!m_selection_enabled)
|
||||
{
|
||||
NetworkString answer(3);
|
||||
NetworkString *answer = getNetworkString(2);
|
||||
// selection still not started
|
||||
answer.ai8(LE_KART_SELECTION_REFUSED).ai8(1).ai8(2);
|
||||
sendMessage(peer, answer);
|
||||
answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(2);
|
||||
peer->sendPacket(answer);
|
||||
delete answer;
|
||||
return;
|
||||
}
|
||||
// check if somebody picked that kart
|
||||
if (!m_setup->isKartAvailable(kart_name))
|
||||
{
|
||||
NetworkString answer(3);
|
||||
NetworkString *answer = getNetworkString(2);
|
||||
// kart is already taken
|
||||
answer.ai8(LE_KART_SELECTION_REFUSED).ai8(1).ai8(0);
|
||||
sendMessage(peer, answer);
|
||||
answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(0);
|
||||
peer->sendPacket(answer);
|
||||
delete answer;
|
||||
return;
|
||||
}
|
||||
// check if this kart is authorized
|
||||
if (!m_setup->isKartAllowed(kart_name))
|
||||
{
|
||||
NetworkString answer(3);
|
||||
NetworkString *answer = getNetworkString(2);
|
||||
// kart is not authorized
|
||||
answer.ai8(LE_KART_SELECTION_REFUSED).ai8(1).ai8(1);
|
||||
sendMessage(peer, answer);
|
||||
answer->addUInt8(LE_KART_SELECTION_REFUSED).addUInt8(1);
|
||||
peer->sendPacket(answer);
|
||||
delete answer;
|
||||
return;
|
||||
}
|
||||
|
||||
// send a kart update to everyone
|
||||
NetworkString answer(3+1+kart_name.size());
|
||||
NetworkString *answer = getNetworkString(3+kart_name.size());
|
||||
// This message must be handled synchronously on the client.
|
||||
answer->setSynchronous(true);
|
||||
// kart update (3), 1, race id
|
||||
uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
|
||||
answer.ai8(LE_KART_SELECTION_UPDATE).ai8(1).ai8(player_id)
|
||||
answer->addUInt8(LE_KART_SELECTION_UPDATE).addUInt8(player_id)
|
||||
.encodeString(kart_name);
|
||||
// This message must be handled synchronously on the client.
|
||||
sendSynchronousMessage(answer);
|
||||
sendMessageToPeersChangingToken(answer);
|
||||
delete answer;
|
||||
m_setup->setPlayerKart(player_id, kart_name);
|
||||
} // kartSelectionRequested
|
||||
|
||||
@@ -581,29 +586,26 @@ void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 10
|
||||
* ----------------------------------------
|
||||
* Size | 1 | 4 | 1 | 4 |
|
||||
* Data | 4 | priv token | 4 | major mode vote |
|
||||
* ----------------------------------------
|
||||
* Byte 0 1
|
||||
* -------------------
|
||||
* Size | 4 |
|
||||
* Data | major mode vote |
|
||||
* -------------------
|
||||
*/
|
||||
void ServerLobbyRoomProtocol::playerMajorVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 1)) return;
|
||||
|
||||
NetworkString &data = event->data();
|
||||
STKPeer* peer = event->getPeer();
|
||||
if (!checkDataSizeAndToken(event, 7))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 4))
|
||||
return;
|
||||
uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
|
||||
uint32_t major = data.getUInt32(6);
|
||||
uint32_t major = data.getUInt32(0);
|
||||
m_setup->getRaceConfig()->setPlayerMajorVote(player_id, major);
|
||||
// Send the vote to everybody (including the sender)
|
||||
data.removeFront(5); // remove the token
|
||||
NetworkString other(5+data.size());
|
||||
other.ai8(1).ai8(player_id); // add the player id
|
||||
other += data; // add the data
|
||||
sendMessageToPeersChangingToken(LE_VOTE_MAJOR, other);
|
||||
NetworkString *other = getNetworkString(6);
|
||||
other->addUInt8(LE_VOTE_MAJOR).addUInt8(player_id).addUInt32(major);
|
||||
sendMessageToPeersChangingToken(other);
|
||||
delete other;
|
||||
} // playerMajorVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -612,28 +614,26 @@ void ServerLobbyRoomProtocol::playerMajorVote(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7
|
||||
* ------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | races count |
|
||||
* ------------------------------------
|
||||
* Byte 0 1
|
||||
* ---------------
|
||||
* Size | 1 |
|
||||
* Data | races count |
|
||||
* ---------------
|
||||
*/
|
||||
void ServerLobbyRoomProtocol::playerRaceCountVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 1)) return;
|
||||
NetworkString &data = event->data();
|
||||
STKPeer* peer = event->getPeer();
|
||||
if (!checkDataSizeAndToken(event, 7))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
|
||||
m_setup->getRaceConfig()->setPlayerRaceCountVote(player_id, data[6]);
|
||||
uint8_t race_count = data[0];
|
||||
m_setup->getRaceConfig()->setPlayerRaceCountVote(player_id, race_count);
|
||||
// Send the vote to everybody (including the sender)
|
||||
data.removeFront(5); // remove the token
|
||||
NetworkString other(2+data.size());
|
||||
other.ai8(1).ai8(player_id); // add the player id
|
||||
other += data; // add the data
|
||||
sendMessageToPeersChangingToken(LE_VOTE_RACE_COUNT, other);
|
||||
NetworkString *other = getNetworkString(3);
|
||||
other->addUInt8(LE_VOTE_RACE_COUNT).addUInt8(player_id)
|
||||
.addUInt8(race_count);
|
||||
sendMessageToPeersChangingToken(other);
|
||||
delete other;
|
||||
} // playerRaceCountVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -642,29 +642,26 @@ void ServerLobbyRoomProtocol::playerRaceCountVote(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 10
|
||||
* ----------------------------------------
|
||||
* Size | 1 | 4 | 1 | 4 |
|
||||
* Data | 4 | priv token | 4 | minor mode vote |
|
||||
* ----------------------------------------
|
||||
* Byte 0 1
|
||||
* -------------------
|
||||
* Size | 4 |
|
||||
* Data | minor mode vote |
|
||||
* -------------------
|
||||
*/
|
||||
void ServerLobbyRoomProtocol::playerMinorVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 1)) return;
|
||||
NetworkString &data = event->data();
|
||||
STKPeer* peer = event->getPeer();
|
||||
if (!checkDataSizeAndToken(event, 7))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 4))
|
||||
return;
|
||||
uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
|
||||
uint32_t minor = data.getUInt32(6);
|
||||
uint32_t minor = data.getUInt32(0);
|
||||
m_setup->getRaceConfig()->setPlayerMinorVote(player_id, minor);
|
||||
|
||||
// Send the vote to everybody (including the sender)
|
||||
data.removeFront(5); // remove the token
|
||||
NetworkString other(2+data.size());
|
||||
other.ai8(1).ai8(player_id); // add the player id
|
||||
other += data; // add the data
|
||||
sendMessageToPeersChangingToken(LE_VOTE_MINOR, other);
|
||||
NetworkString *other = getNetworkString(3);
|
||||
other->addUInt8(LE_VOTE_MINOR).addUInt8(player_id).addUInt8(minor);
|
||||
sendMessageToPeersChangingToken(other);
|
||||
delete other;
|
||||
} // playerMinorVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -673,30 +670,31 @@ void ServerLobbyRoomProtocol::playerMinorVote(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 N+6 N+7 N+8
|
||||
* -----------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | N | 1 | 1 |
|
||||
* Data | 4 | priv token | N | track name | 1 | track number (gp) |
|
||||
* -----------------------------------------------------------
|
||||
* Byte 0 1 2
|
||||
* --------------------------------------
|
||||
* Size | 1 | 1 | N |
|
||||
* Data | track number (gp) | N | track name |
|
||||
* --------------------------------------
|
||||
*/
|
||||
void ServerLobbyRoomProtocol::playerTrackVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 2)) return;
|
||||
NetworkString &data = event->data();
|
||||
STKPeer* peer = event->getPeer();
|
||||
if (!checkDataSizeAndToken(event, 8))
|
||||
return;
|
||||
// As which track this track should be used, e.g. 1st track: Santrack
|
||||
// 2nd track Mathclass, ...
|
||||
uint8_t track_number = data[0];
|
||||
std::string track_name;
|
||||
int N = data.decodeString(5, &track_name);
|
||||
if (!isByteCorrect(event, N+5, 1))
|
||||
return;
|
||||
int N = data.decodeString(1, &track_name);
|
||||
uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
|
||||
m_setup->getRaceConfig()->setPlayerTrackVote(player_id, track_name, data[N+6]);
|
||||
m_setup->getRaceConfig()->setPlayerTrackVote(player_id, track_name,
|
||||
track_number);
|
||||
// Send the vote to everybody (including the sender)
|
||||
data.removeFront(5); // remove the token
|
||||
NetworkString other(2+data.size());
|
||||
other.ai8(1).ai8(player_id); // add the player id
|
||||
other += data; // add the data
|
||||
sendMessageToPeersChangingToken(LE_VOTE_TRACK, other);
|
||||
NetworkString *other = getNetworkString(3+1+data.size());
|
||||
other->addUInt8(LE_VOTE_TRACK).addUInt8(player_id).addUInt8(track_number)
|
||||
.encodeString(track_name);
|
||||
sendMessageToPeersChangingToken(other);
|
||||
delete other;
|
||||
if(m_setup->getRaceConfig()->getNumTrackVotes()==m_setup->getPlayerCount())
|
||||
startGame();
|
||||
} // playerTrackVote
|
||||
@@ -707,31 +705,29 @@ void ServerLobbyRoomProtocol::playerTrackVote(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7 8 9
|
||||
* ---------------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | reversed | 1 | track number (gp) |
|
||||
* ---------------------------------------------------------
|
||||
* Byte 0 1
|
||||
* --------------------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | reversed | track number (gp) |
|
||||
* --------------------------------
|
||||
*/
|
||||
void ServerLobbyRoomProtocol::playerReversedVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 2)) return;
|
||||
|
||||
NetworkString &data = event->data();
|
||||
STKPeer* peer = event->getPeer();
|
||||
if (!checkDataSizeAndToken(event, 9))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 1))
|
||||
return;
|
||||
uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
|
||||
uint8_t reverse = data[0];
|
||||
uint8_t nb_track = data[1];
|
||||
m_setup->getRaceConfig()->setPlayerReversedVote(player_id,
|
||||
data[6]!=0, data[8]);
|
||||
reverse!=0, nb_track);
|
||||
// Send the vote to everybody (including the sender)
|
||||
data.removeFront(5); // remove the token
|
||||
NetworkString other(2+data.size());
|
||||
other.ai8(1).ai8(player_id); // add the player id
|
||||
other += data; // add the data
|
||||
sendMessageToPeersChangingToken(LE_VOTE_REVERSE, other);
|
||||
NetworkString *other = getNetworkString(4);
|
||||
other->addUInt8(LE_VOTE_REVERSE).addUInt8(player_id).addUInt8(reverse)
|
||||
.addUInt8(nb_track);
|
||||
sendMessageToPeersChangingToken(other);
|
||||
delete other;
|
||||
} // playerReversedVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -740,30 +736,27 @@ void ServerLobbyRoomProtocol::playerReversedVote(Event* event)
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7 8 9
|
||||
* -----------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 | 1 | 1 |
|
||||
* Data | 4 | priv token | 1 | laps | 1 | track number (gp) |
|
||||
* -----------------------------------------------------
|
||||
* Byte 0 1
|
||||
* ----------------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | laps | track number (gp) |
|
||||
* ----------------------------
|
||||
*/
|
||||
void ServerLobbyRoomProtocol::playerLapsVote(Event* event)
|
||||
{
|
||||
if (!checkDataSize(event, 2)) return;
|
||||
NetworkString &data = event->data();
|
||||
STKPeer* peer = event->getPeer();
|
||||
if (!checkDataSizeAndToken(event, 9))
|
||||
return;
|
||||
if (!isByteCorrect(event, 5, 1))
|
||||
return;
|
||||
if (!isByteCorrect(event, 7, 1))
|
||||
return;
|
||||
uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
|
||||
m_setup->getRaceConfig()->setPlayerLapsVote(player_id, data[6], data[8]);
|
||||
// Send the vote to everybody (including the sender)
|
||||
data.removeFront(5); // remove the token
|
||||
NetworkString other(2+data.size());
|
||||
other.ai8(1).ai8(player_id); // add the player id
|
||||
other += data; // add the data
|
||||
sendMessageToPeersChangingToken(LE_VOTE_LAPS, other);
|
||||
uint8_t lap_count = data[0];
|
||||
uint8_t track_nb = data[1];
|
||||
m_setup->getRaceConfig()->setPlayerLapsVote(player_id, lap_count,
|
||||
track_nb);
|
||||
NetworkString *other = getNetworkString(4);
|
||||
other->addUInt8(LE_VOTE_LAPS).addUInt8(player_id).addUInt8(lap_count)
|
||||
.addUInt8(track_nb);
|
||||
sendMessageToPeersChangingToken(other);
|
||||
delete other;
|
||||
} // playerLapsVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -123,20 +123,11 @@ void StartGameProtocol::setup()
|
||||
// ----------------------------------------------------------------------------
|
||||
bool StartGameProtocol::notifyEventAsynchronous(Event* event)
|
||||
{
|
||||
if(!checkDataSize(event, 1)) return true;
|
||||
|
||||
const NetworkString &data = event->data();
|
||||
if (data.size() < 5)
|
||||
{
|
||||
Log::error("StartGameProtocol", "Too short message.");
|
||||
return true;
|
||||
}
|
||||
uint32_t token = data.gui32();
|
||||
uint8_t ready = data.gui8(4);
|
||||
uint8_t ready = data.getUInt8(0);
|
||||
STKPeer* peer = event->getPeer();
|
||||
if (peer->getClientServerToken() != token)
|
||||
{
|
||||
Log::error("StartGameProtocol", "Bad token received.");
|
||||
return true;
|
||||
}
|
||||
if (NetworkConfig::get()->isServer() && ready) // on server, player is ready
|
||||
{
|
||||
Log::info("StartGameProtocol", "One of the players is ready.");
|
||||
@@ -219,10 +210,12 @@ void StartGameProtocol::ready()
|
||||
if (NetworkConfig::get()->isClient())
|
||||
{
|
||||
assert(STKHost::get()->getPeerCount() == 1);
|
||||
NetworkString ns(5);
|
||||
ns.ai32(STKHost::get()->getPeers()[0]->getClientServerToken()).ai8(1);
|
||||
NetworkString *ns = getNetworkString(1);
|
||||
// 1 indicates: client is ready
|
||||
ns->addUInt8(1);
|
||||
Log::info("StartGameProtocol", "Player ready, notifying server.");
|
||||
sendMessage(ns, true);
|
||||
sendToServer(ns, /*reliable*/true);
|
||||
delete ns;
|
||||
m_state = READY;
|
||||
m_ready = true;
|
||||
return;
|
||||
|
||||
@@ -42,16 +42,11 @@ bool SynchronizationProtocol::notifyEventAsynchronous(Event* event)
|
||||
{
|
||||
if (event->getType() != EVENT_TYPE_MESSAGE)
|
||||
return true;
|
||||
if(!checkDataSize(event, 5)) return true;
|
||||
|
||||
const NetworkString &data = event->data();
|
||||
if (data.size() < 9)
|
||||
{
|
||||
Log::warn("SynchronizationProtocol", "Received a too short message.");
|
||||
return true;
|
||||
}
|
||||
uint32_t token = data.gui32(0);
|
||||
uint32_t request = data.gui8(4);
|
||||
uint32_t sequence = data.gui32(5);
|
||||
uint32_t request = data.getUInt8(0);
|
||||
uint32_t sequence = data.getUInt32(1);
|
||||
|
||||
const std::vector<STKPeer*> &peers = STKHost::get()->getPeers();
|
||||
assert(peers.size() > 0);
|
||||
@@ -68,28 +63,23 @@ bool SynchronizationProtocol::notifyEventAsynchronous(Event* event)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (event->getPeer()->getClientServerToken() != token)
|
||||
{
|
||||
Log::warn("SynchronizationProtocol", "Bad token from peer %d",
|
||||
peer_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (request)
|
||||
{
|
||||
// Only a client should receive a request for a ping response
|
||||
assert(NetworkConfig::get()->isClient());
|
||||
NetworkString response(10);
|
||||
NetworkString *response = getNetworkString(5);
|
||||
// The '0' indicates a response to a ping request
|
||||
response.ai32(token).ai8(0).ai32(sequence);
|
||||
sendMessage(event->getPeer(), response, false);
|
||||
response->addUInt8(0).addUInt32(sequence);
|
||||
event->getPeer()->sendPacket(response, false);
|
||||
delete response;
|
||||
Log::verbose("SynchronizationProtocol", "Answering sequence %u at %lf",
|
||||
sequence, StkTime::getRealTime());
|
||||
|
||||
// countdown time in the message
|
||||
if (data.size() == 13)
|
||||
if (data.size() == 9)
|
||||
{
|
||||
uint32_t time_to_start = data.gui32(9);
|
||||
uint32_t time_to_start = data.getUInt32(5);
|
||||
Log::debug("SynchronizationProtocol",
|
||||
"Request to start game in %d.", time_to_start);
|
||||
if (!m_countdown_activated)
|
||||
@@ -169,15 +159,15 @@ void SynchronizationProtocol::asynchronousUpdate()
|
||||
const std::vector<STKPeer*> &peers = STKHost::get()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString ping_request(13);
|
||||
ping_request.addUInt32(peers[i]->getClientServerToken())
|
||||
.addUInt8(1).addUInt32(m_pings[i].size());
|
||||
NetworkString *ping_request =
|
||||
getNetworkString(m_countdown_activated ? 9 : 5);
|
||||
ping_request->addUInt8(1).addUInt32(m_pings[i].size());
|
||||
// Server adds the countdown if it has started. This will indicate
|
||||
// to the client to start the countdown as well (first time the
|
||||
// message is received), or to update the countdown time.
|
||||
if (m_countdown_activated )
|
||||
if (m_countdown_activated)
|
||||
{
|
||||
ping_request.addUInt32((int)(m_countdown*1000.0));
|
||||
ping_request->addUInt32((int)(m_countdown*1000.0));
|
||||
Log::debug("SynchronizationProtocol",
|
||||
"CNTActivated: Countdown value : %f", m_countdown);
|
||||
}
|
||||
@@ -185,7 +175,8 @@ void SynchronizationProtocol::asynchronousUpdate()
|
||||
"Added sequence number %u for peer %d at %lf",
|
||||
m_pings[i].size(), i, StkTime::getRealTime());
|
||||
m_pings[i] [ m_pings_count ] = current_time;
|
||||
sendMessage(peers[i], ping_request, false);
|
||||
peers[i]->sendPacket(ping_request, false);
|
||||
delete ping_request;
|
||||
} // for i M peers
|
||||
m_last_time = current_time;
|
||||
m_pings_count++;
|
||||
|
||||
@@ -37,7 +37,7 @@ void RaceEventManager::update(float dt)
|
||||
ProtocolManager::getInstance()->getProtocol(PROTOCOL_SYNCHRONIZATION));
|
||||
if (protocol) // The existance of this protocol indicates that we play online
|
||||
{
|
||||
Log::debug("RaceEventManager", "Coutdown value is %f",
|
||||
Log::debug("RaceEventManager", "Countdown value is %f",
|
||||
protocol->getCountdown());
|
||||
if (protocol->getCountdown() > 0.0)
|
||||
{
|
||||
|
||||
@@ -152,9 +152,9 @@ Online::XMLRequest* ServersManager::getLANRefreshRequest() const
|
||||
{
|
||||
Network *broadcast = new Network(1, 1, 0, 0);
|
||||
|
||||
NetworkString s(std::string("stk-server"));
|
||||
BareNetworkString s(std::string("stk-server"));
|
||||
TransportAddress broadcast_address(-1, 2757);
|
||||
broadcast->sendRawPacket(s.getBytes(), s.size(), broadcast_address);
|
||||
broadcast->sendRawPacket(s, broadcast_address);
|
||||
|
||||
Log::info("ServersManager", "Sent broadcast message.");
|
||||
|
||||
@@ -170,10 +170,10 @@ Online::XMLRequest* ServersManager::getLANRefreshRequest() const
|
||||
int len = broadcast->receiveRawPacket(buffer, LEN, &sender, 1);
|
||||
if(len>0)
|
||||
{
|
||||
NetworkString s(buffer, len);
|
||||
BareNetworkString s(buffer, len);
|
||||
irr::core::stringw name;
|
||||
// name_len is the number of bytes read
|
||||
uint8_t bytes_read = s.decodeStringW(0, &name);
|
||||
// bytes_read is the number of bytes read
|
||||
uint8_t bytes_read = s.decodeStringW(0, &name);
|
||||
uint8_t max_players = s.getUInt8(bytes_read );
|
||||
uint8_t players = s.getUInt8(bytes_read+1);
|
||||
uint32_t my_ip = s.getUInt32(bytes_read+2);
|
||||
|
||||
@@ -434,24 +434,6 @@ bool STKHost::connect(const TransportAddress& address)
|
||||
return true;
|
||||
} // connect
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
/** Sends a message to the server if this is a client, or to all
|
||||
* clients if this is the server.
|
||||
* \param data Message to sent.
|
||||
* \param reliable If the message is to be sent reliable.
|
||||
*/
|
||||
void STKHost::sendMessage(const NetworkString& data, bool reliable)
|
||||
{
|
||||
if (NetworkConfig::get()->isServer())
|
||||
broadcastPacket(data, reliable);
|
||||
else
|
||||
{
|
||||
if (m_peers.size() > 1)
|
||||
Log::warn("ClientNetworkManager", "Ambiguous send of data.");
|
||||
m_peers[0]->sendPacket(data, reliable);
|
||||
}
|
||||
} // sendMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** \brief Starts the listening of events from ENet.
|
||||
* Starts a thread for receiveData that updates it as often as possible.
|
||||
@@ -563,9 +545,10 @@ void* STKHost::mainLoop(void* self)
|
||||
{
|
||||
TransportAddress stk_addr(peer->getAddress());
|
||||
Log::verbose("NetworkManager",
|
||||
"Message, Sender : %s, message = \"%s\"",
|
||||
stk_addr.toString(/*show port*/false).c_str(),
|
||||
stk_event->data().std_string().c_str());
|
||||
"Message, Sender : %s, message:",
|
||||
stk_addr.toString(/*show port*/false).c_str());
|
||||
Log::verbose("NetworkManager", "%s",
|
||||
stk_event->data().getLogMessage().c_str());
|
||||
|
||||
} // if message event
|
||||
|
||||
@@ -590,8 +573,10 @@ void STKHost::handleLANRequests()
|
||||
TransportAddress sender;
|
||||
int len = m_lan_network->receiveRawPacket(buffer, LEN, &sender, 1);
|
||||
if(len<=0) return;
|
||||
|
||||
if (std::string(buffer, len) == "stk-server")
|
||||
BareNetworkString message(buffer, len);
|
||||
std::string command;
|
||||
message.decodeString(0, &command);
|
||||
if (command == "stk-server")
|
||||
{
|
||||
Log::verbose("STKHost", "Received LAN server query");
|
||||
std::string name =
|
||||
@@ -604,15 +589,15 @@ void STKHost::handleLANRequests()
|
||||
// current players, and the client's ip address and port
|
||||
// number (which solves the problem which network interface
|
||||
// might be the right one if there is more than one).
|
||||
NetworkString s;
|
||||
BareNetworkString s(name.size()+1+8);
|
||||
s.encodeString(name);
|
||||
s.addUInt8(NetworkConfig::get()->getMaxPlayers());
|
||||
s.addUInt8(0); // FIXME: current number of connected players
|
||||
s.addUInt32(sender.getIP());
|
||||
s.addUInt16(sender.getPort());
|
||||
m_lan_network->sendRawPacket(s.getBytes(), s.size(), sender);
|
||||
m_lan_network->sendRawPacket(s, sender);
|
||||
} // if message is server-requested
|
||||
else if (std::string(buffer, len) == "connection-request")
|
||||
else if (command == "connection-request")
|
||||
{
|
||||
Protocol *c = new ConnectToPeer(sender);
|
||||
c->requestStart();
|
||||
@@ -653,6 +638,15 @@ STKPeer* STKHost::getPeer(ENetPeer *enet_peer)
|
||||
if(m_peers[i]->isSamePeer(enet_peer))
|
||||
return m_peers[i];
|
||||
}
|
||||
|
||||
// Make sure that a client only adds one other peer (=the server).
|
||||
if(NetworkConfig::get()->isClient() && m_peers.size()>0)
|
||||
{
|
||||
Log::error("STKHost",
|
||||
"Client is adding more than one server, ignored for now.");
|
||||
}
|
||||
|
||||
|
||||
//FIXME Should we check #clients here? It might be easier to only
|
||||
// handle this at connect time, not in all getPeer calls.
|
||||
STKPeer *peer = new STKPeer(enet_peer);
|
||||
@@ -740,7 +734,7 @@ uint16_t STKHost::getPort() const
|
||||
* \param data Data to sent.
|
||||
* \param reliable If the data should be sent reliable or now.
|
||||
*/
|
||||
void STKHost::sendPacketExcept(STKPeer* peer, const NetworkString& data,
|
||||
void STKHost::sendPacketExcept(STKPeer* peer, NetworkString *data,
|
||||
bool reliable)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_peers.size(); i++)
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
#define STK_HOST_HPP
|
||||
|
||||
#include "network/network.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/servers_manager.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
#include "network/transport_address.hpp"
|
||||
#include "utils/synchronised.hpp"
|
||||
|
||||
@@ -40,7 +42,6 @@
|
||||
|
||||
class GameSetup;
|
||||
class NetworkConsole;
|
||||
class STKPeer;
|
||||
|
||||
class STKHost
|
||||
{
|
||||
@@ -145,9 +146,8 @@ public:
|
||||
void requestShutdown();
|
||||
void shutdown();
|
||||
|
||||
void sendMessage(const NetworkString& data, bool reliable = true);
|
||||
void sendPacketExcept(STKPeer* peer,
|
||||
const NetworkString& data,
|
||||
NetworkString *data,
|
||||
bool reliable = true);
|
||||
void setupClient(int peer_count, int channel_limit,
|
||||
uint32_t max_incoming_bandwidth,
|
||||
@@ -181,17 +181,10 @@ public:
|
||||
} // receiveRawPacket
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
void broadcastPacket(const NetworkString& data,
|
||||
bool reliable = true)
|
||||
{
|
||||
m_network->broadcastPacket(data, reliable);
|
||||
} // broadcastPacket
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
void sendRawPacket(uint8_t* data, int length,
|
||||
void sendRawPacket(const BareNetworkString &buffer,
|
||||
const TransportAddress& dst)
|
||||
{
|
||||
m_network->sendRawPacket(data, length, dst);
|
||||
m_network->sendRawPacket(buffer, dst);
|
||||
} // sendRawPacket
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -234,6 +227,12 @@ public:
|
||||
/** Returns the host id of this host. */
|
||||
uint8_t getMyHostId() const { return m_host_id; }
|
||||
// --------------------------------------------------------------------
|
||||
/** Sends a message from a client to the server. */
|
||||
void sendToServer(NetworkString *data, bool reliable = true)
|
||||
{
|
||||
assert(NetworkConfig::get()->isClient());
|
||||
m_peers[0]->sendPacket(data, reliable);
|
||||
} // sendToServer
|
||||
}; // class STKHost
|
||||
|
||||
#endif // STK_HOST_HPP
|
||||
|
||||
@@ -62,13 +62,14 @@ void STKPeer::disconnect()
|
||||
* \param data The data to send.
|
||||
* \param reliable If the data is sent reliable or not.
|
||||
*/
|
||||
void STKPeer::sendPacket(NetworkString const& data, bool reliable)
|
||||
void STKPeer::sendPacket(NetworkString *data, bool reliable)
|
||||
{
|
||||
data->setToken(m_client_server_token);
|
||||
TransportAddress a(m_enet_peer->address);
|
||||
Log::verbose("STKPeer", "sending packet of size %d to %s",
|
||||
data.size(), a.toString().c_str());
|
||||
data->size(), a.toString().c_str());
|
||||
|
||||
ENetPacket* packet = enet_packet_create(data.getBytes(), data.size() + 1,
|
||||
ENetPacket* packet = enet_packet_create(data->getData(), data->size(),
|
||||
(reliable ? ENET_PACKET_FLAG_RELIABLE
|
||||
: ENET_PACKET_FLAG_UNSEQUENCED));
|
||||
enet_peer_send(m_enet_peer, 0, packet);
|
||||
|
||||
@@ -59,7 +59,8 @@ public:
|
||||
STKPeer(ENetPeer *enet_peer);
|
||||
virtual ~STKPeer();
|
||||
|
||||
virtual void sendPacket(const NetworkString& data, bool reliable = true);
|
||||
virtual void sendPacket(NetworkString *data,
|
||||
bool reliable = true);
|
||||
void disconnect();
|
||||
bool isConnected() const;
|
||||
bool exists() const;
|
||||
|
||||
@@ -120,7 +120,7 @@ void ReplayPlay::loadAllReplayFile()
|
||||
fclose(fd);
|
||||
continue;
|
||||
}
|
||||
rd.m_reverse = (bool)reverse;
|
||||
rd.m_reverse = reverse!=0;
|
||||
|
||||
fgets(s, 1023, fd);
|
||||
if (sscanf(s, "difficulty: %u", &rd.m_difficulty) != 1)
|
||||
@@ -247,9 +247,9 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line)
|
||||
pi.m_suspension_length[1] = w2;
|
||||
pi.m_suspension_length[2] = w3;
|
||||
pi.m_suspension_length[3] = w4;
|
||||
kre.m_on_nitro = (bool)nitro;
|
||||
kre.m_on_zipper = (bool)zipper;
|
||||
kre.m_jumping = (bool)jumping;
|
||||
kre.m_on_nitro = nitro!=0;
|
||||
kre.m_on_zipper = zipper!=0;
|
||||
kre.m_jumping = jumping!=0;
|
||||
m_ghost_karts[kart_num].addReplayEvent(time,
|
||||
btTransform(q, xyz), pi, kre);
|
||||
}
|
||||
|
||||
@@ -141,10 +141,9 @@ void NetworkingLobby::eventCallback(Widget* widget, const std::string& name,
|
||||
if(name==m_start_button->m_properties[PROP_ID])
|
||||
{
|
||||
// Send a message to the server to start
|
||||
NetworkString start;
|
||||
start.addUInt8(PROTOCOL_LOBBY_ROOM)
|
||||
.addUInt8(LobbyRoomProtocol::LE_REQUEST_BEGIN);
|
||||
STKHost::get()->sendMessage(start, true);
|
||||
NetworkString start(PROTOCOL_LOBBY_ROOM);
|
||||
start.addUInt8(LobbyRoomProtocol::LE_REQUEST_BEGIN);
|
||||
STKHost::get()->sendToServer(&start, true);
|
||||
}
|
||||
|
||||
RibbonWidget* ribbon = dynamic_cast<RibbonWidget*>(widget);
|
||||
|
||||
Reference in New Issue
Block a user