New packet handling, a more proper way

This commit is contained in:
Loic Blot 2015-01-12 15:59:12 +01:00
parent 32ca9c8b38
commit a9da5e8a44
3 changed files with 222 additions and 101 deletions

View File

@ -1001,40 +1001,100 @@ void Client::Receive()
ProcessData(*data, datasize, sender_peer_id); ProcessData(*data, datasize, sender_peer_id);
} }
/* struct ToClientCommandHandler
sender_peer_id given to this shall be quaranteed to be a valid peer
*/
void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
{ {
DSTACK(__FUNCTION_NAME); char const* name;
void (Client::*handler)(u8 *data, u32 datasize, u16 sender_peer_id);
};
// Ignore packets that don't even fit a command ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
if(datasize < 2)
{ {
m_packetcounter.add(60000); { "TOCLIENT_NULL", &Client::handleCommand_Null },
return; { "TOCLIENT_NULL", &Client::handleCommand_Null },
} { "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_INIT", &Client::handleCommand_Init }, // 0x10
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_ACCESS_DENIED", &Client::handleCommand_AccessDenied }, // 0x35
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
{ "TOCLIENT_NULL", &Client::handleCommand_Null },
};
ToClientCommand command = (ToClientCommand)readU16(&data[0]); void Client::handleCommand_Init(u8 *data, u32 datasize, u16 sender_peer_id)
//infostream<<"Client: received command="<<command<<std::endl;
m_packetcounter.add((u16)command);
/*
If this check is removed, be sure to change the queue
system to know the ids
*/
if(sender_peer_id != PEER_ID_SERVER)
{
infostream<<"Client::ProcessData(): Discarding data not "
"coming from server: peer_id="<<sender_peer_id
<<std::endl;
return;
}
u8 ser_version = m_server_ser_ver;
if(command == TOCLIENT_INIT)
{ {
if(datasize < 3) if(datasize < 3)
return; return;
@ -1088,11 +1148,9 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
m_con.Send(PEER_ID_SERVER, 1, reply, true); m_con.Send(PEER_ID_SERVER, 1, reply, true);
m_state = LC_Init; m_state = LC_Init;
return;
} }
if(command == TOCLIENT_ACCESS_DENIED) void Client::handleCommand_AccessDenied(u8 *data, u32 datasize, u16 sender_peer_id)
{ {
// The server didn't like our password. Note, this needs // The server didn't like our password. Note, this needs
// to be processed even if the serialisation format has // to be processed even if the serialisation format has
@ -1105,37 +1163,24 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
std::istringstream is(datastring, std::ios_base::binary); std::istringstream is(datastring, std::ios_base::binary);
m_access_denied_reason = deSerializeWideString(is); m_access_denied_reason = deSerializeWideString(is);
} }
return;
} }
if(ser_version == SER_FMT_VER_INVALID) void Client::handleCommand_RemoveNode(u8 *data, u32 datasize, u16 sender_peer_id)
{
infostream<<"Client: Server serialization"
" format invalid or not initialized."
" Skipping incoming command="<<command<<std::endl;
return;
}
/*
Handle runtime commands
*/
// there's no sane reason why we shouldn't have a player and
// almost everyone needs a player reference
Player *player = m_env.getLocalPlayer();
assert(player != NULL);
if(command == TOCLIENT_REMOVENODE)
{ {
if(datasize < 8) if(datasize < 8)
return; return;
v3s16 p; v3s16 p;
p.X = readS16(&data[2]); p.X = readS16(&data[2]);
p.Y = readS16(&data[4]); p.Y = readS16(&data[4]);
p.Z = readS16(&data[6]); p.Z = readS16(&data[6]);
removeNode(p); removeNode(p);
} }
else if(command == TOCLIENT_ADDNODE)
void Client::handleCommand_AddNode(u8 *data, u32 datasize, u16 sender_peer_id)
{ {
u8 ser_version = m_server_ser_ver;
if(datasize < 8 + MapNode::serializedLength(ser_version)) if(datasize < 8 + MapNode::serializedLength(ser_version))
return; return;
@ -1155,7 +1200,70 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
addNode(p, n, remove_metadata); addNode(p, n, remove_metadata);
} }
else if(command == TOCLIENT_BLOCKDATA) /*
sender_peer_id given to this shall be quaranteed to be a valid peer
*/
void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
{
DSTACK(__FUNCTION_NAME);
// Ignore packets that don't even fit a command
if(datasize < 2)
{
m_packetcounter.add(60000);
return;
}
ToClientCommand command = (ToClientCommand)readU16(&data[0]);
//infostream<<"Client: received command="<<command<<std::endl;
m_packetcounter.add((u16)command);
/*
If this check is removed, be sure to change the queue
system to know the ids
*/
if(sender_peer_id != PEER_ID_SERVER)
{
infostream<<"Client::ProcessData(): Discarding data not "
"coming from server: peer_id="<<sender_peer_id
<<std::endl;
return;
}
u8 ser_version = m_server_ser_ver;
if(command == TOCLIENT_INIT || command == TOCLIENT_ACCESS_DENIED)
{
ToClientCommandHandler& opHandle = toClientCommandTable[command];
(this->*opHandle.handler)(data, datasize, sender_peer_id);
return;
}
if(ser_version == SER_FMT_VER_INVALID)
{
infostream<<"Client: Server serialization"
" format invalid or not initialized."
" Skipping incoming command="<<command<<std::endl;
return;
}
/*
Handle runtime commands
*/
// there's no sane reason why we shouldn't have a player and
// almost everyone needs a player reference
Player *player = m_env.getLocalPlayer();
assert(player != NULL);
// Handle present here because or m_server_ser_ver (temp i think)
if (command == TOCLIENT_REMOVENODE || command == TOCLIENT_ADDNODE) {
ToClientCommandHandler& opHandle = toClientCommandTable[command];
(this->*opHandle.handler)(data, datasize, sender_peer_id);
return;
}
if(command == TOCLIENT_BLOCKDATA)
{ {
// Ignore too small packet // Ignore too small packet
if(datasize < 8) if(datasize < 8)

View File

@ -339,7 +339,18 @@ public:
*/ */
void step(float dtime); void step(float dtime);
/*
* Command Handler
*/
void handleCommand_Null(u8 *data, u32 datasize, u16 sender_peer_id) {}
void handleCommand_Init(u8 *data, u32 datasize, u16 sender_peer_id);
void handleCommand_AccessDenied(u8 *data, u32 datasize, u16 sender_peer_id);
void handleCommand_RemoveNode(u8 *data, u32 datasize, u16 sender_peer_id);
void handleCommand_AddNode(u8 *data, u32 datasize, u16 sender_peer_id);
void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id); void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id);
// Returns true if something was received // Returns true if something was received
bool AsyncProcessPacket(); bool AsyncProcessPacket();
bool AsyncProcessData(); bool AsyncProcessData();

View File

@ -556,6 +556,8 @@ enum ToClientCommand
v3f1000 first v3f1000 first
v3f1000 third v3f1000 third
*/ */
TOCLIENT_NUM_MSG_TYPES = 0x53,
}; };
enum ToServerCommand enum ToServerCommand