From a9da5e8a443abffabb77094dd1e2fbd5ec18f081 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Mon, 12 Jan 2015 15:59:12 +0100 Subject: [PATCH] New packet handling, a more proper way --- src/client.cpp | 310 ++++++++++++++++++++++++++++++--------------- src/client.h | 11 ++ src/clientserver.h | 2 + 3 files changed, 222 insertions(+), 101 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 536e9afa7..26c7f7ec3 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1001,6 +1001,205 @@ void Client::Receive() ProcessData(*data, datasize, sender_peer_id); } +struct ToClientCommandHandler +{ + char const* name; + void (Client::*handler)(u8 *data, u32 datasize, u16 sender_peer_id); +}; + +ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] = +{ + { "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_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 }, +}; + +void Client::handleCommand_Init(u8 *data, u32 datasize, u16 sender_peer_id) +{ + if(datasize < 3) + return; + + u8 deployed = data[2]; + + infostream<<"Client: TOCLIENT_INIT received with " + "deployed="<<((int)deployed&0xff)<= 2+1+6) + playerpos_s16 = readV3S16(&data[2+1]); + v3f playerpos_f = intToFloat(playerpos_s16, BS) - v3f(0, BS/2, 0); + + + // Set player position + Player *player = m_env.getLocalPlayer(); + assert(player != NULL); + player->setPosition(playerpos_f); + + if(datasize >= 2+1+6+8) + { + // Get map seed + m_map_seed = readU64(&data[2+1+6]); + infostream<<"Client: received map seed: "<= 2+1+6+8+4) + { + // Get map seed + m_recommended_send_interval = readF1000(&data[2+1+6+8]); + infostream<<"Client: received recommended send interval " + < reply(replysize); + writeU16(&reply[0], TOSERVER_INIT2); + // Send as reliable + m_con.Send(PEER_ID_SERVER, 1, reply, true); + + m_state = LC_Init; +} + +void Client::handleCommand_AccessDenied(u8 *data, u32 datasize, u16 sender_peer_id) +{ + // The server didn't like our password. Note, this needs + // to be processed even if the serialisation format has + // not been agreed yet, the same as TOCLIENT_INIT. + m_access_denied = true; + m_access_denied_reason = L"Unknown"; + if(datasize >= 4) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + m_access_denied_reason = deSerializeWideString(is); + } +} + +void Client::handleCommand_RemoveNode(u8 *data, u32 datasize, u16 sender_peer_id) +{ + if(datasize < 8) + return; + + v3s16 p; + p.X = readS16(&data[2]); + p.Y = readS16(&data[4]); + p.Z = readS16(&data[6]); + removeNode(p); +} + +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)) + return; + + v3s16 p; + p.X = readS16(&data[2]); + p.Y = readS16(&data[4]); + p.Z = readS16(&data[6]); + + MapNode n; + n.deSerialize(&data[8], ser_version); + + bool remove_metadata = true; + u32 index = 8 + MapNode::serializedLength(ser_version); + if ((datasize >= index+1) && data[index]){ + remove_metadata = false; + } + + addNode(p, n, remove_metadata); +} /* sender_peer_id given to this shall be quaranteed to be a valid peer */ @@ -1034,77 +1233,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) u8 ser_version = m_server_ser_ver; - if(command == TOCLIENT_INIT) + if(command == TOCLIENT_INIT || command == TOCLIENT_ACCESS_DENIED) { - if(datasize < 3) - return; - - u8 deployed = data[2]; - - infostream<<"Client: TOCLIENT_INIT received with " - "deployed="<<((int)deployed&0xff)<= 2+1+6) - playerpos_s16 = readV3S16(&data[2+1]); - v3f playerpos_f = intToFloat(playerpos_s16, BS) - v3f(0, BS/2, 0); - - - // Set player position - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - player->setPosition(playerpos_f); - - if(datasize >= 2+1+6+8) - { - // Get map seed - m_map_seed = readU64(&data[2+1+6]); - infostream<<"Client: received map seed: "<= 2+1+6+8+4) - { - // Get map seed - m_recommended_send_interval = readF1000(&data[2+1+6+8]); - infostream<<"Client: received recommended send interval " - < reply(replysize); - writeU16(&reply[0], TOSERVER_INIT2); - // Send as reliable - m_con.Send(PEER_ID_SERVER, 1, reply, true); - - m_state = LC_Init; - - return; - } - - if(command == TOCLIENT_ACCESS_DENIED) - { - // The server didn't like our password. Note, this needs - // to be processed even if the serialisation format has - // not been agreed yet, the same as TOCLIENT_INIT. - m_access_denied = true; - m_access_denied_reason = L"Unknown"; - if(datasize >= 4) - { - std::string datastring((char*)&data[2], datasize-2); - std::istringstream is(datastring, std::ios_base::binary); - m_access_denied_reason = deSerializeWideString(is); - } + ToClientCommandHandler& opHandle = toClientCommandTable[command]; + (this->*opHandle.handler)(data, datasize, sender_peer_id); return; } @@ -1123,39 +1255,15 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) // almost everyone needs a player reference Player *player = m_env.getLocalPlayer(); assert(player != NULL); - - if(command == TOCLIENT_REMOVENODE) - { - if(datasize < 8) - return; - v3s16 p; - p.X = readS16(&data[2]); - p.Y = readS16(&data[4]); - p.Z = readS16(&data[6]); - removeNode(p); + + // 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; } - else if(command == TOCLIENT_ADDNODE) - { - if(datasize < 8 + MapNode::serializedLength(ser_version)) - return; - v3s16 p; - p.X = readS16(&data[2]); - p.Y = readS16(&data[4]); - p.Z = readS16(&data[6]); - - MapNode n; - n.deSerialize(&data[8], ser_version); - - bool remove_metadata = true; - u32 index = 8 + MapNode::serializedLength(ser_version); - if ((datasize >= index+1) && data[index]){ - remove_metadata = false; - } - - addNode(p, n, remove_metadata); - } - else if(command == TOCLIENT_BLOCKDATA) + if(command == TOCLIENT_BLOCKDATA) { // Ignore too small packet if(datasize < 8) diff --git a/src/client.h b/src/client.h index 898fc4daa..e50a44369 100644 --- a/src/client.h +++ b/src/client.h @@ -339,7 +339,18 @@ public: */ 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); + // Returns true if something was received bool AsyncProcessPacket(); bool AsyncProcessData(); diff --git a/src/clientserver.h b/src/clientserver.h index 5f7864768..6d3e77c5b 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -556,6 +556,8 @@ enum ToClientCommand v3f1000 first v3f1000 third */ + + TOCLIENT_NUM_MSG_TYPES = 0x53, }; enum ToServerCommand