From e55e39a9797cea87941a82bc5feaf46dc1544e98 Mon Sep 17 00:00:00 2001 From: lotodore Date: Sun, 30 Jan 2011 18:28:44 +0000 Subject: [PATCH] Chat cleaner now active within ranking games (for testing it is also active in normal games). New protocol version for chat cleaner. --- src/chatcleaner/cleanerserver.cpp | 276 +++++++++++++------------- src/net/chatcleanercallback.h | 1 + src/net/chatcleanermanager.h | 3 +- src/net/common/chatcleanermanager.cpp | 30 ++- src/net/common/clientstate.cpp | 1 + src/net/common/servergamestate.cpp | 11 + src/net/common/serverlobbythread.cpp | 33 ++- src/net/internalchatcleanerpacket.h | 2 +- src/net/serverlobbythread.h | 3 +- 9 files changed, 217 insertions(+), 143 deletions(-) diff --git a/src/chatcleaner/cleanerserver.cpp b/src/chatcleaner/cleanerserver.cpp index 04420b14..76da4bb3 100644 --- a/src/chatcleaner/cleanerserver.cpp +++ b/src/chatcleaner/cleanerserver.cpp @@ -13,192 +13,194 @@ using namespace std; CleanerServer::CleanerServer(): config(0), blockConnection(false), m_recvBufUsed(0), secondsSinceLastConfigChange(0) { - config = new CleanerConfig; + config = new CleanerConfig; - clientSecret = QString::fromUtf8(config->readConfigString("ClientAuthString").c_str()); - serverSecret = QString::fromUtf8(config->readConfigString("ServerAuthString").c_str()); + clientSecret = QString::fromUtf8(config->readConfigString("ClientAuthString").c_str()); + serverSecret = QString::fromUtf8(config->readConfigString("ServerAuthString").c_str()); - myMessageFilter = new MessageFilter(config); - tcpServer = new QTcpServer(); - tcpServer->setMaxPendingConnections(1); + myMessageFilter = new MessageFilter(config); + tcpServer = new QTcpServer(); + tcpServer->setMaxPendingConnections(1); - if (!tcpServer->listen(QHostAddress(QString::fromUtf8(config->readConfigString("HostAddress").c_str())), config->readConfigInt("DefaultListenPort")) ) { - qDebug() << QString("Unable to start the server: %1.").arg(tcpServer->errorString()); - return; - } - qDebug() << QString("The server is running on port %1.").arg(tcpServer->serverPort()); + if (!tcpServer->listen(QHostAddress(QString::fromUtf8(config->readConfigString("HostAddress").c_str())), config->readConfigInt("DefaultListenPort")) ) { + qDebug() << QString("Unable to start the server: %1.").arg(tcpServer->errorString()); + return; + } + qDebug() << QString("The server is running on port %1.").arg(tcpServer->serverPort()); - configRefreshTimer = new QTimer(); + configRefreshTimer = new QTimer(); - connect(configRefreshTimer, SIGNAL(timeout()), this, SLOT(refreshConfig())); - connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newCon())); + connect(configRefreshTimer, SIGNAL(timeout()), this, SLOT(refreshConfig())); + connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newCon())); - refreshConfig(); - configRefreshTimer->start(10000); + refreshConfig(); + configRefreshTimer->start(10000); } CleanerServer::~CleanerServer() { - delete config; - delete myMessageFilter; - delete tcpServer; - delete configRefreshTimer; + delete config; + delete myMessageFilter; + delete tcpServer; + delete configRefreshTimer; } void CleanerServer::newCon() { - if(!blockConnection) { - tcpSocket = tcpServer->nextPendingConnection(); - connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(onRead())); - connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState))); - blockConnection = true; - } + if(!blockConnection) { + tcpSocket = tcpServer->nextPendingConnection(); + connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(onRead())); + connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState))); + blockConnection = true; + } } void CleanerServer::onRead() { - qint64 bytesRead = tcpSocket->read((char *)m_recvBuf + m_recvBufUsed, sizeof(m_recvBuf) - m_recvBufUsed); - bool error = bytesRead < 1; - if (!error) - { - m_recvBufUsed += bytesRead; + qint64 bytesRead = tcpSocket->read((char *)m_recvBuf + m_recvBufUsed, sizeof(m_recvBuf) - m_recvBufUsed); + bool error = bytesRead < 1; + if (!error) + { + m_recvBufUsed += bytesRead; - asn_dec_rval_t retVal; - do - { - // Try to decode the packets. - InternalChatCleanerPacket recvMsg; - retVal = ber_decode(0, &asn_DEF_ChatCleanerMessage, (void **)recvMsg.GetMsgPtr(), m_recvBuf, m_recvBufUsed); - if(retVal.code == RC_OK) - { - if (retVal.consumed < m_recvBufUsed) - { - m_recvBufUsed -= retVal.consumed; - memmove(m_recvBuf, m_recvBuf + retVal.consumed, m_recvBufUsed); - } - else - m_recvBufUsed = 0; + asn_dec_rval_t retVal; + do + { + // Try to decode the packets. + InternalChatCleanerPacket recvMsg; + retVal = ber_decode(0, &asn_DEF_ChatCleanerMessage, (void **)recvMsg.GetMsgPtr(), m_recvBuf, m_recvBufUsed); + if(retVal.code == RC_OK) + { + if (retVal.consumed < m_recvBufUsed) + { + m_recvBufUsed -= retVal.consumed; + memmove(m_recvBuf, m_recvBuf + retVal.consumed, m_recvBufUsed); + } + else + m_recvBufUsed = 0; - // Handle the packets. - error = handleMessage(recvMsg); - } - } while (!error && retVal.code == RC_OK); - } + // Handle the packets. + error = handleMessage(recvMsg); + } + } while (!error && retVal.code == RC_OK); + } - if (error) - { - qDebug() << "Error handling packets from client."; - tcpSocket->close(); - } + if (error) + { + qDebug() << "Error handling packets from client."; + tcpSocket->close(); + } - /* char buf[1024]; - tcpSocket->readLine(buf, sizeof(buf)); + /* char buf[1024]; + tcpSocket->readLine(buf, sizeof(buf)); QString message = QString::fromUtf8("%1").arg(buf); - + // TESTING DEFAULT VALUES QString nick = "PlayerNick"; unsigned playerId = 1; // TESTING DEFAULT VALUES - + QString checkMessage = myMessageFilter->check(playerId, nick, message); tcpSocket->write(checkMessage.toAscii().data(), checkMessage.length());*/ } bool CleanerServer::handleMessage(InternalChatCleanerPacket &msg) { - bool error = true; - if (msg.GetMsg()->present == ChatCleanerMessage_PR_cleanerInitMessage) - { - CleanerInitMessage_t *netInit = &msg.GetMsg()->choice.cleanerInitMessage; - if (netInit->requestedVersion == CLEANER_PROTOCOL_VERSION) - { - string tmpClientSecret((const char *)netInit->clientSecret.buf, netInit->clientSecret.size); - if (clientSecret == QString::fromStdString(tmpClientSecret)) - { - error = false; + bool error = true; + if (msg.GetMsg()->present == ChatCleanerMessage_PR_cleanerInitMessage) + { + CleanerInitMessage_t *netInit = &msg.GetMsg()->choice.cleanerInitMessage; + if (netInit->requestedVersion == CLEANER_PROTOCOL_VERSION) + { + string tmpClientSecret((const char *)netInit->clientSecret.buf, netInit->clientSecret.size); + if (clientSecret == QString::fromStdString(tmpClientSecret)) + { + error = false; - InternalChatCleanerPacket tmpAck; - tmpAck.GetMsg()->present = ChatCleanerMessage_PR_cleanerInitAckMessage; - CleanerInitAckMessage_t *netAck = &tmpAck.GetMsg()->choice.cleanerInitAckMessage; - netAck->serverVersion = CLEANER_PROTOCOL_VERSION; - string tmpServerSecret(serverSecret.toStdString()); - OCTET_STRING_fromBuf(&netAck->serverSecret, - tmpServerSecret.c_str(), - tmpServerSecret.length()); - sendMessageToClient(tmpAck); - } - else - qDebug() << "Invalid client secret."; - } - else - qDebug() << "Invalid client version: " << netInit->requestedVersion; - } - else if (msg.GetMsg()->present == ChatCleanerMessage_PR_cleanerChatRequestMessage) - { - error = false; - CleanerChatRequestMessage_t *netRequest = &msg.GetMsg()->choice.cleanerChatRequestMessage; - unsigned playerId = netRequest->playerId; - QString nick(QString::fromUtf8( - string((const char *)netRequest->playerName.buf, netRequest->playerName.size).c_str())); - QString message(QString::fromUtf8( - string((const char *)netRequest->chatMessage.buf, netRequest->chatMessage.size).c_str())); - QStringList checkreturn = myMessageFilter->check(playerId, nick, message); - QString checkAction = checkreturn.at(0); - QString checkMessage = checkreturn.at(1); + InternalChatCleanerPacket tmpAck; + tmpAck.GetMsg()->present = ChatCleanerMessage_PR_cleanerInitAckMessage; + CleanerInitAckMessage_t *netAck = &tmpAck.GetMsg()->choice.cleanerInitAckMessage; + netAck->serverVersion = CLEANER_PROTOCOL_VERSION; + string tmpServerSecret(serverSecret.toStdString()); + OCTET_STRING_fromBuf(&netAck->serverSecret, + tmpServerSecret.c_str(), + tmpServerSecret.length()); + sendMessageToClient(tmpAck); + } + else + qDebug() << "Invalid client secret."; + } + else + qDebug() << "Invalid client version: " << netInit->requestedVersion; + } + else if (msg.GetMsg()->present == ChatCleanerMessage_PR_cleanerChatRequestMessage) + { + error = false; + CleanerChatRequestMessage_t *netRequest = &msg.GetMsg()->choice.cleanerChatRequestMessage; + unsigned playerId = netRequest->playerId; + QString nick(QString::fromUtf8( + string((const char *)netRequest->playerName.buf, netRequest->playerName.size).c_str())); + QString message(QString::fromUtf8( + string((const char *)netRequest->chatMessage.buf, netRequest->chatMessage.size).c_str())); + QStringList checkreturn = myMessageFilter->check(playerId, nick, message); + QString checkAction = checkreturn.at(0); + QString checkMessage = checkreturn.at(1); - if (!checkAction.isEmpty()) - { - InternalChatCleanerPacket tmpReply; - tmpReply.GetMsg()->present = ChatCleanerMessage_PR_cleanerChatReplyMessage; - CleanerChatReplyMessage_t *netReply = &tmpReply.GetMsg()->choice.cleanerChatReplyMessage; - netReply->requestId = netRequest->requestId; - netReply->playerId = netRequest->playerId; + if (!checkAction.isEmpty()) + { + InternalChatCleanerPacket tmpReply; + tmpReply.GetMsg()->present = ChatCleanerMessage_PR_cleanerChatReplyMessage; + CleanerChatReplyMessage_t *netReply = &tmpReply.GetMsg()->choice.cleanerChatReplyMessage; + netReply->requestId = netRequest->requestId; + netReply->cleanerChatType = netRequest->cleanerChatType; + netReply->playerId = netRequest->playerId; - if(checkAction == "warn") { - netReply->cleanerActionType = cleanerActionType_cleanerActionWarning; - } - else if(checkAction == "kick") { - netReply->cleanerActionType = cleanerActionType_cleanerActionKick; - } - else if(checkAction == "kickban") { - netReply->cleanerActionType = cleanerActionType_cleanerActionBan; - } + if(checkAction == "warn") { + netReply->cleanerActionType = cleanerActionType_cleanerActionWarning; + } + else if(checkAction == "kick") { + netReply->cleanerActionType = cleanerActionType_cleanerActionKick; + } + else if(checkAction == "kickban") { + netReply->cleanerActionType = cleanerActionType_cleanerActionBan; + } - string tmpCheck(checkMessage.toUtf8()); - netReply->cleanerText = - OCTET_STRING_new_fromBuf( - &asn_DEF_OCTET_STRING, - (const char *)tmpCheck.c_str(), - tmpCheck.length()); - sendMessageToClient(tmpReply); - } - } - return error; + string tmpCheck(checkMessage.toUtf8()); + netReply->cleanerText = + OCTET_STRING_new_fromBuf( + &asn_DEF_OCTET_STRING, + (const char *)tmpCheck.c_str(), + tmpCheck.length()); + sendMessageToClient(tmpReply); + } + } + return error; } void CleanerServer::socketStateChanged(QAbstractSocket::SocketState state) { - qDebug() << "Socket state changed to: " << QAbstractSocket::UnconnectedState; - if(state == QAbstractSocket::UnconnectedState) blockConnection = false; + qDebug() << "Socket state changed to: " << QAbstractSocket::UnconnectedState; + if(state == QAbstractSocket::UnconnectedState) blockConnection = false; } void CleanerServer::refreshConfig() { - QFileInfo configFileInfo(QString::fromUtf8(config->getConfigFileName().c_str())); + QFileInfo configFileInfo(QString::fromUtf8(config->getConfigFileName().c_str())); - if(configFileInfo.lastModified().secsTo(QDateTime::currentDateTime()) < 20) { - config->fillBuffer(); - } + if(configFileInfo.lastModified().secsTo(QDateTime::currentDateTime()) < 20) { + config->fillBuffer(); + } - myMessageFilter->refreshConfig(); + myMessageFilter->refreshConfig(); } void CleanerServer::sendMessageToClient(InternalChatCleanerPacket &msg) { - unsigned char buf[MAX_CLEANER_PACKET_SIZE]; - asn_enc_rval_t e = der_encode_to_buffer(&asn_DEF_ChatCleanerMessage, msg.GetMsg(), buf, MAX_CLEANER_PACKET_SIZE); + unsigned char buf[MAX_CLEANER_PACKET_SIZE]; + asn_enc_rval_t e = der_encode_to_buffer(&asn_DEF_ChatCleanerMessage, msg.GetMsg(), buf, MAX_CLEANER_PACKET_SIZE); - if (e.encoded == -1) - qDebug() << "Failed to encode chat cleaner packet: " << msg.GetMsg()->present; - else - tcpSocket->write((const char *)buf, e.encoded); + if (e.encoded == -1) + qDebug() << "Failed to encode chat cleaner packet: " << msg.GetMsg()->present; + else + tcpSocket->write((const char *)buf, e.encoded); } + diff --git a/src/net/chatcleanercallback.h b/src/net/chatcleanercallback.h index d888e18f..0140bc03 100644 --- a/src/net/chatcleanercallback.h +++ b/src/net/chatcleanercallback.h @@ -30,6 +30,7 @@ public: virtual ~ChatCleanerCallback(); virtual void SignalChatBotMessage(const std::string &msg) = 0; + virtual void SignalChatBotMessage(unsigned gameId, const std::string &msg) = 0; virtual void SignalKickPlayer(unsigned playerId) = 0; virtual void SignalBanPlayer(unsigned playerId) = 0; }; diff --git a/src/net/chatcleanermanager.h b/src/net/chatcleanermanager.h index 4863eddf..eec1495f 100644 --- a/src/net/chatcleanermanager.h +++ b/src/net/chatcleanermanager.h @@ -38,7 +38,8 @@ public: void Init(const std::string &serverAddr, int port, bool ipv6, const std::string &clientSecret, const std::string &serverSecret); void ReInit(); - void HandleChatText(unsigned playerId, const std::string &name, const std::string &text); + void HandleLobbyChatText(unsigned playerId, const std::string &name, const std::string &text); + void HandleGameChatText(unsigned gameId, unsigned playerId, const std::string &name, const std::string &text); protected: diff --git a/src/net/common/chatcleanermanager.cpp b/src/net/common/chatcleanermanager.cpp index 941c1e70..987ec7fe 100644 --- a/src/net/common/chatcleanermanager.cpp +++ b/src/net/common/chatcleanermanager.cpp @@ -74,7 +74,13 @@ ChatCleanerManager::ReInit() } void -ChatCleanerManager::HandleChatText(unsigned playerId, const std::string &name, const std::string &text) +ChatCleanerManager::HandleLobbyChatText(unsigned playerId, const std::string &name, const std::string &text) +{ + HandleGameChatText(0, playerId, name, text); +} + +void +ChatCleanerManager::HandleGameChatText(unsigned gameId, unsigned playerId, const std::string &name, const std::string &text) { if (m_connected) { @@ -82,6 +88,15 @@ ChatCleanerManager::HandleChatText(unsigned playerId, const std::string &name, c tmpChat.GetMsg()->present = ChatCleanerMessage_PR_cleanerChatRequestMessage; CleanerChatRequestMessage_t *netRequest = &tmpChat.GetMsg()->choice.cleanerChatRequestMessage; netRequest->requestId = GetNextRequestId(); + if (gameId) + { + netRequest->cleanerChatType.present = CleanerChatType_PR_cleanerChatTypeGame; + netRequest->cleanerChatType.choice.cleanerChatTypeGame.gameId = gameId; + } + else + { + netRequest->cleanerChatType.present = CleanerChatType_PR_cleanerChatTypeLobby; + } netRequest->playerId = playerId; OCTET_STRING_fromBuf(&netRequest->playerName, name.c_str(), @@ -252,7 +267,16 @@ ChatCleanerManager::HandleMessage(InternalChatCleanerPacket &msg) { CleanerChatReplyMessage_t *netReply = &msg.GetMsg()->choice.cleanerChatReplyMessage; if (netReply->cleanerText) - m_callback.SignalChatBotMessage(string((const char *)netReply->cleanerText->buf, netReply->cleanerText->size)); + { + if (netReply->cleanerChatType.present == CleanerChatType_PR_cleanerChatTypeLobby) + { + m_callback.SignalChatBotMessage(string((const char *)netReply->cleanerText->buf, netReply->cleanerText->size)); + } + else if (netReply->cleanerChatType.present == CleanerChatType_PR_cleanerChatTypeGame) + { + m_callback.SignalChatBotMessage(netReply->cleanerChatType.choice.cleanerChatTypeGame.gameId, string((const char *)netReply->cleanerText->buf, netReply->cleanerText->size)); + } + } if (netReply->cleanerActionType == cleanerActionType_cleanerActionKick) m_callback.SignalKickPlayer(netReply->playerId); else if (netReply->cleanerActionType == cleanerActionType_cleanerActionBan) @@ -273,6 +297,8 @@ ChatCleanerManager::SendMessageToServer(InternalChatCleanerPacket &msg) else { boost::shared_ptr tmpPacket(new EncodedPacket(buf, e.encoded)); + // Actually, this should not be done (parallel async_write calls might break data). + // But we do not want to create additional buffers here. boost::asio::async_write( *m_socket, boost::asio::buffer(tmpPacket->GetData(), tmpPacket->GetSize()), diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 565e99e9..9c667865 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -767,6 +767,7 @@ AbstractClientStateReceiving::HandlePacket(boost::shared_ptr clien } else if (netMessage->chatType.present == chatType_PR_chatTypeBot) { + client->GetCallback().SignalNetClientGameChatMsg("(chat bot)", STL_STRING_FROM_OCTET_STRING(netMessage->chatText)); client->GetCallback().SignalNetClientLobbyChatMsg("(chat bot)", STL_STRING_FROM_OCTET_STRING(netMessage->chatText)); } else if (netMessage->chatType.present == chatType_PR_chatTypeGame) diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index 98f39fcf..3a636744 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -291,6 +292,16 @@ AbstractServerGameStateReceiving::ProcessPacket(boost::shared_ptr se (char *)netChatRequest->chatText.buf, netChatRequest->chatText.size); server->SendToAllPlayers(packet, SessionData::Game); + + // Send the message to the chat cleaner bot for ranking games. + //if (server->GetGameData().gameType == GAME_TYPE_RANKING) + //{ + server->GetLobbyThread().GetChatCleaner().HandleGameChatText( + server->GetId(), + session.playerData->GetUniqueId(), + session.playerData->GetName(), + string((char *)netChatRequest->chatText.buf, netChatRequest->chatText.size)); + //} } } } diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index a28228dd..02e4098f 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -103,6 +103,11 @@ public: m_server.SendChatBotMsg(msg); } + virtual void SignalChatBotMessage(unsigned gameId, const std::string &msg) + { + m_server.SendChatBotMsg(gameId, msg); + } + virtual void SignalKickPlayer(unsigned playerId) { m_server.RemovePlayer(playerId, ERR_NET_PLAYER_KICKED); @@ -611,6 +616,25 @@ ServerLobbyThread::SendChatBotMsg(const std::string &message) message); } +void +ServerLobbyThread::SendChatBotMsg(unsigned gameId, const std::string &message) +{ + boost::shared_ptr packet(new NetPacket(NetPacket::Alloc)); + packet->GetMsg()->present = PokerTHMessage_PR_chatMessage; + ChatMessage_t *netChat = &packet->GetMsg()->choice.chatMessage; + netChat->chatType.present = chatType_PR_chatTypeBot; + OCTET_STRING_fromBuf( + &netChat->chatText, + message.c_str(), + message.length()); + + GameMap::const_iterator pos = m_gameMap.find(gameId); + if (pos != m_gameMap.end()) + { + pos->second->SendToAllPlayers(packet, SessionData::Game); + } +} + void ServerLobbyThread::ReconnectChatBot() { @@ -650,6 +674,13 @@ ServerLobbyThread::GetAvatarManager() return m_avatarManager; } +ChatCleanerManager & +ServerLobbyThread::GetChatCleaner() +{ + assert(m_chatCleanerManager); + return *m_chatCleanerManager; +} + ServerStats ServerLobbyThread::GetStats() const { @@ -1466,7 +1497,7 @@ ServerLobbyThread::HandleNetPacketChatRequest(SessionWrapper session, const Chat string chatMsg = STL_STRING_FROM_OCTET_STRING(chatRequest.chatText); // Send the message to the chat cleaner bot. - m_chatCleanerManager->HandleChatText( + m_chatCleanerManager->HandleLobbyChatText( session.playerData->GetUniqueId(), session.playerData->GetName(), chatMsg); diff --git a/src/net/internalchatcleanerpacket.h b/src/net/internalchatcleanerpacket.h index 5b7b7e81..efe80387 100644 --- a/src/net/internalchatcleanerpacket.h +++ b/src/net/internalchatcleanerpacket.h @@ -21,7 +21,7 @@ #ifndef _INTERNALCHATCLEANERPACKET_H_ #define _INTERNALCHATCLEANERPACKET_H_ -#define CLEANER_PROTOCOL_VERSION 1 +#define CLEANER_PROTOCOL_VERSION 2 #define MAX_CLEANER_PACKET_SIZE 384 typedef struct ChatCleanerMessage ChatCleanerMessage_t; diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index c4a0548f..49210778 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -83,10 +83,10 @@ public: std::string GetPlayerNameFromId(unsigned playerId) const; void RemovePlayer(unsigned playerId, unsigned errorCode); - void SendGlobalChat(const std::string &message); void SendGlobalMsgBox(const std::string &message); void SendChatBotMsg(const std::string &message); + void SendChatBotMsg(unsigned gameId, const std::string &message); void ReconnectChatBot(); void AddComputerPlayer(boost::shared_ptr player); @@ -101,6 +101,7 @@ public: void SetGameDBId(u_int32_t gameId, DB_id gameDBId); AvatarManager &GetAvatarManager(); + ChatCleanerManager &GetChatCleaner(); ServerStats GetStats() const; boost::posix_time::ptime GetStartTime() const;