From d068c6203de6a37875d32a028ef6d2874708ec4d Mon Sep 17 00:00:00 2001 From: lotodore Date: Fri, 14 Aug 2009 18:56:45 +0000 Subject: [PATCH] Adding client for chat cleaner. --- pokerth_lib.pro | 4 + src/net/chatcleanermanager.h | 69 +++++++ src/net/common/chatcleanermanager.cpp | 283 ++++++++++++++++++++++++++ src/net/common/encodedpacket.cpp | 36 ++++ src/net/common/netpacket.cpp | 3 +- src/net/common/senderhelper.cpp | 33 +-- src/net/encodedpacket.h | 47 +++++ 7 files changed, 442 insertions(+), 33 deletions(-) create mode 100644 src/net/chatcleanermanager.h create mode 100644 src/net/common/chatcleanermanager.cpp create mode 100644 src/net/common/encodedpacket.cpp create mode 100644 src/net/encodedpacket.h diff --git a/pokerth_lib.pro b/pokerth_lib.pro index 5e4ba2eb..66056bd7 100644 --- a/pokerth_lib.pro +++ b/pokerth_lib.pro @@ -63,6 +63,7 @@ HEADERS += \ src/engine/playerinterface.h \ src/engine/berointerface.h \ src/gui/guiinterface.h \ + src/net/chatcleanermanager.h \ src/net/clientcallback.h \ src/net/clientcontext.h \ src/net/clientexception.h \ @@ -97,6 +98,7 @@ HEADERS += \ src/net/uploadhelper.h \ src/net/downloaderthread.h \ src/net/downloadhelper.h \ + src/net/encodedpacket.h \ src/third_party/tinyxml/tinystr.h \ src/third_party/tinyxml/tinyxml.h \ src/third_party/libircclient/include/libircclient.h \ @@ -162,6 +164,7 @@ SOURCES += \ src/engine/network_engine/clienthand.cpp \ src/engine/network_engine/clientplayer.cpp \ src/engine/network_engine/clientbero.cpp \ + src/net/common/chatcleanermanager.cpp \ src/net/common/clientcallback.cpp \ src/net/common/clientcontext.cpp \ src/net/common/clientstate.cpp \ @@ -192,6 +195,7 @@ SOURCES += \ src/net/common/transferhelper.cpp \ src/net/common/uploaderthread.cpp \ src/net/common/uploadhelper.cpp \ + src/net/common/encodedpacket.cpp \ src/gui/generic/serverguiwrapper.cpp \ src/gui/qttoolsinterface.cpp diff --git a/src/net/chatcleanermanager.h b/src/net/chatcleanermanager.h new file mode 100644 index 00000000..a86895fb --- /dev/null +++ b/src/net/chatcleanermanager.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2009 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * 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. * + ***************************************************************************/ +/* Manager which acts as client for the chat cleaner service. */ + +#ifndef _CHATCLEANERMANAGER_H_ +#define _CHATCLEANERMANAGER_H_ + +#include +#include +#include + +#define CLEANER_PROTOCOL_VERSION 1 +#define MAX_CLEANER_PACKET_SIZE 384 + +class InternalChatCleanerMessage; +class EncodedPacket; + +class ChatCleanerManager : public boost::enable_shared_from_this +{ +public: + ChatCleanerManager(boost::shared_ptr ioService); + virtual ~ChatCleanerManager(); + + void Init(const std::string &serverAddr, int port, bool ipv6, + const std::string &clientSecret, const std::string &serverSecret); + void HandleChatText(unsigned playerId, const std::string &name, const std::string &text); + +protected: + + void HandleResolve(const boost::system::error_code& ec, boost::asio::ip::tcp::resolver::iterator endpoint_iterator); + void HandleConnect(const boost::system::error_code& ec, boost::asio::ip::tcp::resolver::iterator endpoint_iterator); + void HandleWrite(const boost::system::error_code &ec, boost::shared_ptr tmpPacket); + void HandleRead(const boost::system::error_code &ec, size_t bytesRead); + bool HandleMessage(InternalChatCleanerMessage &msg); + + void SendMessageToServer(InternalChatCleanerMessage &msg); + unsigned GetNextRequestId(); + +private: + + boost::shared_ptr m_ioService; + boost::shared_ptr m_resolver; + boost::shared_ptr m_socket; + + bool m_connected; + unsigned m_curRequestId; + std::string m_clientSecret; + std::string m_serverSecret; + unsigned char m_recvBuf[2*MAX_CLEANER_PACKET_SIZE]; + unsigned m_recvBufUsed; +}; + +#endif diff --git a/src/net/common/chatcleanermanager.cpp b/src/net/common/chatcleanermanager.cpp new file mode 100644 index 00000000..94604768 --- /dev/null +++ b/src/net/common/chatcleanermanager.cpp @@ -0,0 +1,283 @@ +/*************************************************************************** + * Copyright (C) 2009 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * 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 +#include +#include +#include +#include + + +using namespace std; +using boost::asio::ip::tcp; + +class InternalChatCleanerMessage +{ +public: + InternalChatCleanerMessage() + { + m_msg = (ChatCleanerMessage_t *)calloc(1, sizeof(ChatCleanerMessage_t)); + } + InternalChatCleanerMessage(ChatCleanerMessage_t *msg) + : m_msg(msg) + { + } + ~InternalChatCleanerMessage() + { + if (m_msg) + ASN_STRUCT_FREE(asn_DEF_ChatCleanerMessage, m_msg); + } + ChatCleanerMessage_t *GetMsg() + { + return m_msg; + } + ChatCleanerMessage_t **GetMsgPtr() + { + return &m_msg; + } + +private: + ChatCleanerMessage_t *m_msg; +}; + + +ChatCleanerManager::ChatCleanerManager(boost::shared_ptr ioService) +: m_ioService(ioService), m_connected(false), m_curRequestId(0), m_recvBufUsed(0) +{ + m_resolver.reset( + new boost::asio::ip::tcp::resolver(*m_ioService)); +} + +ChatCleanerManager::~ChatCleanerManager() +{ +} + +void +ChatCleanerManager::Init(const string &serverAddr, int port, bool ipv6, + const string &clientSecret, const string &serverSecret) +{ + m_clientSecret = clientSecret; + m_serverSecret = serverSecret; + if (ipv6) + m_socket.reset(new boost::asio::ip::tcp::socket(*m_ioService, tcp::v6())); + else + m_socket.reset(new boost::asio::ip::tcp::socket(*m_ioService, tcp::v4())); + + ostringstream portStr; + portStr << port; + boost::asio::ip::tcp::resolver::query q(serverAddr, portStr.str()); + + m_resolver->async_resolve( + q, + boost::bind(&ChatCleanerManager::HandleResolve, + shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::iterator)); +} + +void +ChatCleanerManager::HandleChatText(unsigned playerId, const std::string &name, const std::string &text) +{ + if (m_connected) + { + InternalChatCleanerMessage tmpChat; + tmpChat.GetMsg()->present = ChatCleanerMessage_PR_cleanerChatRequestMessage; + CleanerChatRequestMessage_t *netRequest = &tmpChat.GetMsg()->choice.cleanerChatRequestMessage; + netRequest->requestId = GetNextRequestId(); + netRequest->playerId = playerId; + OCTET_STRING_fromBuf(&netRequest->playerName, + name.c_str(), + name.length()); + OCTET_STRING_fromBuf(&netRequest->chatMessage, + text.c_str(), + text.length()); + SendMessageToServer(tmpChat); + } +} + +void +ChatCleanerManager::HandleResolve(const boost::system::error_code& ec, + boost::asio::ip::tcp::resolver::iterator endpoint_iterator) +{ + if (!ec) + { + boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; + m_socket->async_connect( + endpoint, + boost::bind(&ChatCleanerManager::HandleConnect, + shared_from_this(), + boost::asio::placeholders::error, + ++endpoint_iterator)); + } + else if (ec != boost::asio::error::operation_aborted) + { + LOG_ERROR("Could not resolve chat cleaner server."); + } +} + +void +ChatCleanerManager::HandleConnect(const boost::system::error_code& ec, + boost::asio::ip::tcp::resolver::iterator endpoint_iterator) +{ + if (!ec) + { + InternalChatCleanerMessage tmpInit; + tmpInit.GetMsg()->present = ChatCleanerMessage_PR_cleanerInitMessage; + CleanerInitMessage_t *netInit = &tmpInit.GetMsg()->choice.cleanerInitMessage; + netInit->requestedVersion = CLEANER_PROTOCOL_VERSION; + OCTET_STRING_fromBuf(&netInit->clientSecret, + m_clientSecret.c_str(), + m_clientSecret.length()); + SendMessageToServer(tmpInit); + m_socket->async_read_some( + boost::asio::buffer(m_recvBuf, sizeof(m_recvBuf)), + boost::bind( + &ChatCleanerManager::HandleRead, + shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) + { + // Try next resolve entry. + m_socket->close(); + boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; + m_socket->async_connect( + endpoint, + boost::bind(&ChatCleanerManager::HandleConnect, + shared_from_this(), + boost::asio::placeholders::error, + ++endpoint_iterator)); + } + else if (ec != boost::asio::error::operation_aborted) + { + LOG_ERROR("Could not connect to chat cleaner server."); + } +} + +void +ChatCleanerManager::HandleWrite(const boost::system::error_code &ec, + boost::shared_ptr /*tmpPacket*/) +{ + if (ec && ec != boost::asio::error::operation_aborted) + { + LOG_ERROR("Error sending message to chat cleaner."); + m_socket->close(); + m_connected = false; + } +} + +void +ChatCleanerManager::HandleRead(const boost::system::error_code &ec, size_t bytesRead) +{ + if (!ec) + { + bool error = false; + m_recvBufUsed += bytesRead; + + InternalChatCleanerMessage recvMsg; + asn_dec_rval_t retVal = ber_decode(0, &asn_DEF_ChatCleanerMessage, (void **)recvMsg.GetMsgPtr(), m_recvBuf, m_recvBufUsed); + if(retVal.code == RC_OK) + { + // Consume the bytes. + if (retVal.consumed < m_recvBufUsed) + { + m_recvBufUsed -= retVal.consumed; + memmove(m_recvBuf, m_recvBuf + retVal.consumed, m_recvBufUsed); + } + else + m_recvBufUsed = 0; + + error = HandleMessage(recvMsg); + } + + if (!error) + { + m_socket->async_read_some( + boost::asio::buffer(m_recvBuf + m_recvBufUsed, sizeof(m_recvBuf) - m_recvBufUsed), + boost::bind( + &ChatCleanerManager::HandleRead, + shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + } + else if (ec != boost::asio::error::operation_aborted) + { + LOG_ERROR("Error receiving data from chat cleaner."); + m_socket->close(); + m_connected = false; + } +} + +bool +ChatCleanerManager::HandleMessage(InternalChatCleanerMessage &msg) +{ + bool error = false; + if (msg.GetMsg()->present == ChatCleanerMessage_PR_cleanerInitAckMessage) + { + CleanerInitAckMessage_t *netAck = &msg.GetMsg()->choice.cleanerInitAckMessage; + if (netAck->serverVersion == CLEANER_PROTOCOL_VERSION) + { + string tmpSecret((const char *)netAck->serverSecret.buf, netAck->serverSecret.size); + if (m_serverSecret == tmpSecret) + m_connected = true; + } + if (!m_connected) + { + LOG_ERROR("Chat cleaner handshake failed."); + m_socket->close(); + error = true; + } + } + return error; +} +#define STL_STRING_FROM_OCTET_STRING(_a) (string((const char *)_a.buf, _a.size)) + +void +ChatCleanerManager::SendMessageToServer(InternalChatCleanerMessage &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); + + if (e.encoded == -1) + LOG_ERROR("Failed to encode chat cleaner packet: " << msg.GetMsg()->present); + else + { + boost::shared_ptr tmpPacket(new EncodedPacket(buf, e.encoded)); + boost::asio::async_write( + *m_socket, + boost::asio::buffer(tmpPacket->GetData(), tmpPacket->GetSize()), + boost::bind(&ChatCleanerManager::HandleWrite, + shared_from_this(), + boost::asio::placeholders::error, + tmpPacket)); + } +} + +unsigned +ChatCleanerManager::GetNextRequestId() +{ + m_curRequestId++; + if (m_curRequestId == 0) // 0 is an invalid id. + m_curRequestId++; + + return m_curRequestId; +} + diff --git a/src/net/common/encodedpacket.cpp b/src/net/common/encodedpacket.cpp new file mode 100644 index 00000000..34f1c65e --- /dev/null +++ b/src/net/common/encodedpacket.cpp @@ -0,0 +1,36 @@ +/*************************************************************************** + * Copyright (C) 2009 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * 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 +#include + +using namespace std; + +EncodedPacket::EncodedPacket(const unsigned char *data, unsigned size) +: m_size(size) +{ + m_data = new unsigned char[size]; + memcpy(m_data, data, size); +} + +EncodedPacket::~EncodedPacket() +{ + delete[] m_data; +} + diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index 586b7f74..afe8a85b 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -43,8 +43,7 @@ NetPacket::Create(char *data, unsigned &dataSize) if (data && dataSize > 0) { PokerTHMessage_t *msg = NULL; - asn_dec_rval_t retVal; - retVal = ber_decode(0, &asn_DEF_PokerTHMessage, (void **)&msg, data, dataSize); + asn_dec_rval_t retVal = ber_decode(0, &asn_DEF_PokerTHMessage, (void **)&msg, data, dataSize); if(retVal.code == RC_OK) { // ASN.1 BER decoding was successful. diff --git a/src/net/common/senderhelper.cpp b/src/net/common/senderhelper.cpp index 441a5843..21b91163 100644 --- a/src/net/common/senderhelper.cpp +++ b/src/net/common/senderhelper.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -38,35 +39,6 @@ using boost::asio::ip::tcp; #define SEND_QUEUE_SIZE 10000000 #define SEND_LOG_INTERVAL_SEC 60 -class EncodedPacket -{ -public: - EncodedPacket(const unsigned char *data, unsigned size) - : m_size(size) - { - m_data = new unsigned char[size]; - memcpy(m_data, data, size); - } - - ~EncodedPacket() - { - delete[] m_data; - } - - unsigned GetSize() const - { - return m_size; - } - - const unsigned char *GetData() const - { - return m_data; - } - -private: - unsigned m_size; - unsigned char *m_data; -}; typedef std::list > SendDataList; @@ -234,8 +206,7 @@ void SenderHelper::InternalStorePacket(SendDataManager &tmpManager, boost::shared_ptr packet) { unsigned char buf[MAX_PACKET_SIZE]; - asn_enc_rval_t e; - e = der_encode_to_buffer(&asn_DEF_PokerTHMessage, packet->GetMsg(), buf, MAX_PACKET_SIZE); + asn_enc_rval_t e = der_encode_to_buffer(&asn_DEF_PokerTHMessage, packet->GetMsg(), buf, MAX_PACKET_SIZE); //cerr << "OUT:" << endl << packet->ToString() << endl; if (e.encoded == -1) LOG_ERROR("Failed to encode NetPacket: " << packet->GetMsg()->present); diff --git a/src/net/encodedpacket.h b/src/net/encodedpacket.h new file mode 100644 index 00000000..fcfc0b50 --- /dev/null +++ b/src/net/encodedpacket.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2009 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * 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. * + ***************************************************************************/ +/* PokerTH encoded packet. */ + +#ifndef _ENCODEDPACKET_H_ +#define _ENCODEDPACKET_H_ + + +class EncodedPacket +{ +public: + EncodedPacket(const unsigned char *data, unsigned size); + ~EncodedPacket(); + + unsigned GetSize() const + { + return m_size; + } + + const unsigned char *GetData() const + { + return m_data; + } + +private: + unsigned m_size; + unsigned char *m_data; +}; + +#endif +