From 7ddf67aa1478813e12a5fcdfb4986b9e5adfe62f Mon Sep 17 00:00:00 2001 From: Loïc Blot Date: Sun, 16 Jul 2017 10:47:31 +0200 Subject: Chat protocol rewrite (#5117) * New TOCLIENT_CHAT_MESSAGE packet * Rename old packet to TOCLIENT_CHAT_MESSAGE_OLD for compat * Handle TOCLIENT_CHAT_MESSAGE new structure client side * Client chat queue should use a specific object * SendChatMessage: use the right packet depending on protocol version (not complete yet) * Add chatmessage(type) objects and handle them client side (partially) * Use ChatMessage instead of std::wstring server side * Update with timestamp support --- src/network/clientopcodes.cpp | 4 ++-- src/network/clientpackethandler.cpp | 44 ++++++++++++++++++++++++++++++++++--- src/network/networkpacket.cpp | 16 ++++++++++++++ src/network/networkpacket.h | 3 +++ src/network/networkprotocol.h | 22 +++++++++++++++++-- src/network/serveropcodes.cpp | 4 ++-- src/network/serverpackethandler.cpp | 31 ++++++++++++++++---------- 7 files changed, 104 insertions(+), 20 deletions(-) (limited to 'src/network') diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp index cb504b373..f39dd6db6 100644 --- a/src/network/clientopcodes.cpp +++ b/src/network/clientopcodes.cpp @@ -71,8 +71,8 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] = null_command_handler, null_command_handler, null_command_handler, - null_command_handler, - { "TOCLIENT_CHAT_MESSAGE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ChatMessage }, // 0x30 + { "TOCLIENT_CHAT_MESSAGE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ChatMessage }, // 0x2F + { "TOCLIENT_CHAT_MESSAGE_OLD", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ChatMessageOld }, // 0x30 { "TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ActiveObjectRemoveAdd }, // 0x31 { "TOCLIENT_ACTIVE_OBJECT_MESSAGES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ActiveObjectMessages }, // 0x32 { "TOCLIENT_HP", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HP }, // 0x33 diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index e6f0d7092..bb4db6f47 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client.h" #include "util/base64.h" +#include "chatmessage.h" #include "clientmedia.h" #include "log.h" #include "map.h" @@ -142,7 +143,9 @@ void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt) } void Client::handleCommand_DenySudoMode(NetworkPacket* pkt) { - pushToChatQueue(L"Password change denied. Password NOT changed."); + ChatMessage *chatMessage = new ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Password change denied. Password NOT changed."); + pushToChatQueue(chatMessage); // reset everything and be sad deleteAuthData(); } @@ -395,7 +398,7 @@ void Client::handleCommand_TimeOfDay(NetworkPacket* pkt) << " dr=" << dr << std::endl; } -void Client::handleCommand_ChatMessage(NetworkPacket* pkt) +void Client::handleCommand_ChatMessageOld(NetworkPacket *pkt) { /* u16 command @@ -413,8 +416,43 @@ void Client::handleCommand_ChatMessage(NetworkPacket* pkt) } // If chat message not consummed by client lua API + // @TODO send this to CSM using ChatMessage object if (!moddingEnabled() || !m_script->on_receiving_message(wide_to_utf8(message))) { - pushToChatQueue(message); + pushToChatQueue(new ChatMessage(message)); + } +} + +void Client::handleCommand_ChatMessage(NetworkPacket *pkt) +{ + /* + u8 version + u8 message_type + u16 sendername length + wstring sendername + u16 length + wstring message + */ + + ChatMessage *chatMessage = new ChatMessage(); + u8 version, message_type; + *pkt >> version >> message_type; + + if (version != 1 || message_type >= CHATMESSAGE_TYPE_MAX) { + delete chatMessage; + return; + } + + *pkt >> chatMessage->sender >> chatMessage->message >> chatMessage->timestamp; + + chatMessage->type = (ChatMessageType) message_type; + + // @TODO send this to CSM using ChatMessage object + if (!moddingEnabled() || !m_script->on_receiving_message( + wide_to_utf8(chatMessage->message))) { + pushToChatQueue(chatMessage); + } else { + // Message was consumed by CSM and should not handled by client, destroying + delete chatMessage; } } diff --git a/src/network/networkpacket.cpp b/src/network/networkpacket.cpp index 48cf3a374..78c73d253 100644 --- a/src/network/networkpacket.cpp +++ b/src/network/networkpacket.cpp @@ -275,6 +275,12 @@ NetworkPacket& NetworkPacket::operator<<(u64 src) return *this; } +NetworkPacket& NetworkPacket::operator<<(std::time_t src) +{ + *this << (u64) src; + return *this; +} + NetworkPacket& NetworkPacket::operator<<(float src) { checkDataSize(4); @@ -360,6 +366,16 @@ NetworkPacket& NetworkPacket::operator>>(u64& dst) return *this; } +NetworkPacket& NetworkPacket::operator>>(std::time_t& dst) +{ + checkReadOffset(m_read_offset, 8); + + dst = readU64(&m_data[m_read_offset]); + + m_read_offset += 8; + return *this; +} + NetworkPacket& NetworkPacket::operator>>(float& dst) { checkReadOffset(m_read_offset, 4); diff --git a/src/network/networkpacket.h b/src/network/networkpacket.h index 3058a22ca..7eb8cc3ff 100644 --- a/src/network/networkpacket.h +++ b/src/network/networkpacket.h @@ -84,6 +84,9 @@ public: NetworkPacket& operator>>(u64& dst); NetworkPacket& operator<<(u64 src); + NetworkPacket& operator>>(std::time_t& dst); + NetworkPacket& operator<<(std::time_t src); + NetworkPacket& operator>>(float& dst); NetworkPacket& operator<<(float src); diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 8304d3003..759334839 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -160,9 +160,17 @@ with this program; if not, write to the Free Software Foundation, Inc., instead of guessing based on the active object list. PROTOCOL VERSION 34: Add sound pitch + PROTOCOL VERSION 35: + Rename TOCLIENT_CHAT_MESSAGE to TOCLIENT_CHAT_MESSAGE_OLD (0x30) + Add TOCLIENT_CHAT_MESSAGE (0x2F) + This chat message is a signalisation message containing various informations: + * timestamp + * sender + * type (RAW, NORMAL, ANNOUNCE, SYSTEM) + * content */ -#define LATEST_PROTOCOL_VERSION 34 +#define LATEST_PROTOCOL_VERSION 35 // Server's supported network protocol range #define SERVER_PROTOCOL_VERSION_MIN 24 @@ -307,7 +315,17 @@ enum ToClientCommand // (oops, there is some gap here) - TOCLIENT_CHAT_MESSAGE = 0x30, + TOCLIENT_CHAT_MESSAGE = 0x2F, + /* + u8 version + u8 message_type + u16 sendername length + wstring sendername + u16 length + wstring message + */ + + TOCLIENT_CHAT_MESSAGE_OLD = 0x30, // Deprecated by proto v35 /* u16 length wstring message diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp index 3f9706d6a..208214369 100644 --- a/src/network/serveropcodes.cpp +++ b/src/network/serveropcodes.cpp @@ -160,8 +160,8 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] = null_command_factory, null_command_factory, null_command_factory, - null_command_factory, - { "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x30 + { "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x2F + { "TOCLIENT_CHAT_MESSAGE_OLD", 0, true }, // 0x30 { "TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD", 0, true }, // 0x31 { "TOCLIENT_ACTIVE_OBJECT_MESSAGES", 0, true }, // 0x32 Special packet, sent by 0 (rel) and 1 (unrel) channel { "TOCLIENT_HP", 0, true }, // 0x33 diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index a2882b2e7..b87daba6b 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include "server.h" #include "log.h" @@ -644,8 +645,10 @@ void Server::handleCommand_Init2(NetworkPacket* pkt) // Warnings about protocol version can be issued here if (getClient(pkt->getPeerId())->net_proto_version < LATEST_PROTOCOL_VERSION) { - SendChatMessage(pkt->getPeerId(), L"# Server: WARNING: YOUR CLIENT'S " - L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!"); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"# Server: WARNING: YOUR CLIENT'S VERSION MAY NOT BE FULLY COMPATIBLE " + L"WITH THIS SERVER!")); + } } @@ -1077,11 +1080,11 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt) std::string name = player->getName(); std::wstring wname = narrow_to_wide(name); - std::wstring answer_to_sender = handleChat(name, wname, message, - true, dynamic_cast(player)); + std::wstring answer_to_sender = handleChat(name, wname, message, true, player); if (!answer_to_sender.empty()) { // Send the answer to sender - SendChatMessage(pkt->getPeerId(), answer_to_sender); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_NORMAL, + answer_to_sender, wname)); } } @@ -1171,7 +1174,8 @@ void Server::handleCommand_Password(NetworkPacket* pkt) infostream<<"Server: " << player->getName() << " supplied invalid password hash" << std::endl; // Wrong old password supplied!! - SendChatMessage(pkt->getPeerId(), L"Invalid new password hash supplied. Password NOT changed."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Invalid new password hash supplied. Password NOT changed.")); return; } @@ -1186,18 +1190,21 @@ void Server::handleCommand_Password(NetworkPacket* pkt) if (oldpwd != checkpwd) { infostream << "Server: invalid old password" << std::endl; // Wrong old password supplied!! - SendChatMessage(pkt->getPeerId(), L"Invalid old password supplied. Password NOT changed."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Invalid old password supplied. Password NOT changed.")); return; } bool success = m_script->setPassword(playername, newpwd); if (success) { actionstream << player->getName() << " changes password" << std::endl; - SendChatMessage(pkt->getPeerId(), L"Password change successful."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Password change successful.")); } else { actionstream << player->getName() << " tries to change password but " << "it fails" << std::endl; - SendChatMessage(pkt->getPeerId(), L"Password change failed or unavailable."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Password change failed or unavailable.")); } } @@ -1853,11 +1860,13 @@ void Server::handleCommand_FirstSrp(NetworkPacket* pkt) bool success = m_script->setPassword(playername, pw_db_field); if (success) { actionstream << playername << " changes password" << std::endl; - SendChatMessage(pkt->getPeerId(), L"Password change successful."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Password change successful.")); } else { actionstream << playername << " tries to change password but " << "it fails" << std::endl; - SendChatMessage(pkt->getPeerId(), L"Password change failed or unavailable."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Password change failed or unavailable.")); } } } -- cgit v1.2.3