Adding client for chat cleaner.
This commit is contained in:
@@ -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 <net/chatcleanermanager.h>
|
||||
#include <net/encodedpacket.h>
|
||||
#include <boost/bind.hpp>
|
||||
#include <core/loghelper.h>
|
||||
#include <third_party/asn1/ChatCleanerMessage.h>
|
||||
|
||||
|
||||
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<boost::asio::io_service> 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<EncodedPacket> /*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<EncodedPacket> 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;
|
||||
}
|
||||
|
||||
@@ -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 <net/encodedpacket.h>
|
||||
#include <cstring>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <net/sendercallback.h>
|
||||
#include <net/socket_helper.h>
|
||||
#include <net/socket_msg.h>
|
||||
#include <net/encodedpacket.h>
|
||||
#include <core/loghelper.h>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
@@ -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<boost::shared_ptr<EncodedPacket> > SendDataList;
|
||||
|
||||
@@ -234,8 +206,7 @@ void
|
||||
SenderHelper::InternalStorePacket(SendDataManager &tmpManager, boost::shared_ptr<NetPacket> 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);
|
||||
|
||||
Reference in New Issue
Block a user