From f34b6b1babbb1b78a460651f22aeb4169fd62d9c Mon Sep 17 00:00:00 2001 From: Henrique Date: Wed, 27 Jul 2011 15:10:49 -0300 Subject: [PATCH] connection rework, entergame.lua fix --- data/modules/mainmenu/entergame.lua | 2 +- src/framework/net/connection.cpp | 61 +++++++++++------------------ src/framework/net/connection.h | 26 ++++-------- src/framework/net/protocol.cpp | 42 +++++++++++++++----- src/framework/net/protocol.h | 16 ++++++-- src/protocollogin.cpp | 14 +++---- 6 files changed, 83 insertions(+), 78 deletions(-) diff --git a/data/modules/mainmenu/entergame.lua b/data/modules/mainmenu/entergame.lua index 7bfa8bda..dba2ae5a 100644 --- a/data/modules/mainmenu/entergame.lua +++ b/data/modules/mainmenu/entergame.lua @@ -41,7 +41,7 @@ function EnterGame_connectToLoginServer() local motdBox = displayInfoBox("Message of the day", motdText) -- cancel protocol and reacreate enter game window - protocol.cancel() + protocol:cancel() motdBox.onOk = recreateEnterGame end diff --git a/src/framework/net/connection.cpp b/src/framework/net/connection.cpp index d46b2f64..9654c399 100644 --- a/src/framework/net/connection.cpp +++ b/src/framework/net/connection.cpp @@ -27,7 +27,6 @@ static boost::asio::io_service ioService; Connection::Connection() : - m_connectionState(CONNECTION_STATE_IDLE), m_timer(ioService), m_resolver(ioService), m_socket(ioService) @@ -43,7 +42,6 @@ void Connection::poll() void Connection::connect(const std::string& host, uint16 port, const std::function& connectCallback) { m_connectCallback = connectCallback; - m_connectionState = CONNECTION_STATE_RESOLVING; boost::asio::ip::tcp::resolver::query query(host, convert(port)); m_resolver.async_resolve(query, std::bind(&Connection::onResolve, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); @@ -52,16 +50,31 @@ void Connection::connect(const std::string& host, uint16 port, const std::functi m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); } -void Connection::send(OutputMessage *outputMessage) +void Connection::send(uint8 *buffer, uint16 size) { boost::asio::async_write(m_socket, - boost::asio::buffer(outputMessage->getBuffer(), outputMessage->getMessageSize()), + boost::asio::buffer(buffer, size), std::bind(&Connection::onSend, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); m_timer.expires_from_now(boost::posix_time::seconds(2)); m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); } +void Connection::recv(uint16 bytes, uint32 timeout, const RecvCallback& callback) +{ + m_recvCallback = callback; + m_recvSize = bytes; + + boost::asio::async_read(m_socket, + boost::asio::buffer(m_recvBuffer, bytes), + std::bind(&Connection::onRecv, shared_from_this(), std::placeholders::_1)); + + if(timeout > 0) { + m_timer.expires_from_now(boost::posix_time::seconds(timeout)); + m_timer.async_wait(std::bind(&Connection::onTimeout, shared_from_this(), std::placeholders::_1)); + } +} + void Connection::onTimeout(const boost::system::error_code& error) { if(error != boost::asio::error::operation_aborted) @@ -94,12 +107,8 @@ void Connection::onConnect(const boost::system::error_code& error) return; } - g_dispatcher.addTask(m_connectCallback); - - // Start listening. - boost::asio::async_read(m_socket, - boost::asio::buffer(m_inputMessage.getBuffer(), InputMessage::HEADER_LENGTH), - std::bind(&Connection::onRecvHeader, shared_from_this(), std::placeholders::_1)); + if(m_connectCallback) + g_dispatcher.addTask(m_connectCallback); } void Connection::onSend(const boost::system::error_code& error, size_t) @@ -113,42 +122,16 @@ void Connection::onSend(const boost::system::error_code& error, size_t) } } -void Connection::onRecvHeader(const boost::system::error_code& error) +void Connection::onRecv(const boost::system::error_code& error) { - if(error) { - if(m_errorCallback) - g_dispatcher.addTask(std::bind(m_errorCallback, error)); - return; - } - - uint16 messageSize = m_inputMessage.getU16(); - m_inputMessage.setMessageSize(messageSize); - - boost::asio::async_read(m_socket, - boost::asio::buffer(m_inputMessage.getBuffer() + InputMessage::CHECKSUM_POS, messageSize), - std::bind(&Connection::onRecvData, shared_from_this(), std::placeholders::_1)); -} + m_timer.cancel(); -void Connection::onRecvData(const boost::system::error_code& error) -{ if(error) { if(m_errorCallback) g_dispatcher.addTask(std::bind(m_errorCallback, error)); return; } - // call callback - // must be called outside dispatcher cause of inputmessage. if(m_recvCallback) - m_recvCallback(&m_inputMessage); - //g_dispatcher.addTask(std::bind(m_recvCallback, &m_inputMessage)); - - // keep reading - - // TODO: lua code must be reworked. - /*m_inputMessage.reset(); - boost::asio::async_read(m_socket, - boost::asio::buffer(m_inputMessage.getBuffer(), InputMessage::HEADER_LENGTH), - std::bind(&Connection::onRecvHeader, shared_from_this(), std::placeholders::_1));*/ - + g_dispatcher.addTask(std::bind(m_recvCallback, m_recvBuffer, m_recvSize)); } diff --git a/src/framework/net/connection.h b/src/framework/net/connection.h index af5e237a..d21f1734 100644 --- a/src/framework/net/connection.h +++ b/src/framework/net/connection.h @@ -26,14 +26,10 @@ #define CONNECTION_H #include - -#include -#include - #include typedef std::function ErrorCallback; -typedef std::function RecvCallback; +typedef std::function RecvCallback; class Connection : public std::enable_shared_from_this, boost::noncopyable { @@ -43,7 +39,9 @@ public: static void poll(); void connect(const std::string& host, uint16 port, const std::function& connectCallback); - void send(OutputMessage *outputMessage); + void send(uint8 *buffer, uint16 size); + void recv(uint16 bytes, uint32 timeout, const RecvCallback& callback); + void recv(const std::string& data, uint32 timeout, const RecvCallback& callback); void setErrorCallback(const ErrorCallback& errorCallback) { m_errorCallback = errorCallback; } void setRecvCallback(const RecvCallback& recvCallback) { m_recvCallback = recvCallback; } @@ -52,27 +50,19 @@ public: void onResolve(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator endpointIterator); void onConnect(const boost::system::error_code& error); void onSend(const boost::system::error_code& error, size_t); - void onRecvHeader(const boost::system::error_code& error); - void onRecvData(const boost::system::error_code& error); - - enum ConnectionState_t { - CONNECTION_STATE_IDLE = 0, - CONNECTION_STATE_RESOLVING, - CONNECTION_STATE_CONNECTING, - CONNECTION_STATE_CONNECTED - }; + void onRecv(const boost::system::error_code& error); private: ErrorCallback m_errorCallback; - RecvCallback m_recvCallback; std::function m_connectCallback; - ConnectionState_t m_connectionState; boost::asio::deadline_timer m_timer; boost::asio::ip::tcp::resolver m_resolver; boost::asio::ip::tcp::socket m_socket; - InputMessage m_inputMessage; + uint8 m_recvBuffer[65536]; + uint16 m_recvSize; + RecvCallback m_recvCallback; }; typedef std::shared_ptr ConnectionPtr; diff --git a/src/framework/net/protocol.cpp b/src/framework/net/protocol.cpp index fd16055b..2284fb9b 100644 --- a/src/framework/net/protocol.cpp +++ b/src/framework/net/protocol.cpp @@ -30,13 +30,12 @@ Protocol::Protocol() : m_connection(new Connection) { m_connection->setErrorCallback(std::bind(&Protocol::onError, this, std::placeholders::_1)); - m_connection->setRecvCallback(std::bind(&Protocol::onRecv, this, std::placeholders::_1)); m_xteaEncryptionEnabled = false; } -void Protocol::connect(const std::string& host, uint16 port, const std::function& callback) +void Protocol::connect(const std::string& host, uint16 port) { - m_connection->connect(host, port, callback); + m_connection->connect(host, port, std::bind(&Protocol::onConnect, asProtocol())); } void Protocol::send(OutputMessage *outputMessage) @@ -56,30 +55,56 @@ void Protocol::send(OutputMessage *outputMessage) outputMessage->addU16(messageSize); // Send - m_connection->send(outputMessage); + m_connection->send(outputMessage->getBuffer(), outputMessage->getMessageSize()); } -void Protocol::onRecv(InputMessage *inputMessage) +void Protocol::recv() { - uint32 checksum = getAdlerChecksum(inputMessage->getBuffer() + InputMessage::DATA_POS, inputMessage->getMessageSize() - InputMessage::CHECKSUM_LENGTH); - if(inputMessage->getU32() != checksum) { + m_inputMessage.reset(); + + m_connection->recv(InputMessage::HEADER_LENGTH, 2, std::bind(&Protocol::internalRecvHeader, asProtocol(), std::placeholders::_1, std::placeholders::_2)); +} + +void Protocol::internalRecvHeader(uint8 *buffer, uint16 size) +{ + memcpy(m_inputMessage.getBuffer() + InputMessage::HEADER_POS, buffer, size); + + uint16 dataSize = m_inputMessage.getU16(); + m_inputMessage.setMessageSize(dataSize); + + m_connection->recv(dataSize, 5, std::bind(&Protocol::internalRecvData, asProtocol(), std::placeholders::_1, std::placeholders::_2)); +} + +void Protocol::internalRecvData(uint8 *buffer, uint16 size) +{ + memcpy(m_inputMessage.getBuffer() + InputMessage::CHECKSUM_POS, buffer, size); + + uint32 checksum = getAdlerChecksum(m_inputMessage.getBuffer() + InputMessage::DATA_POS, m_inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH); + if(m_inputMessage.getU32() != checksum) { // error logError("Checksum is invalid."); return; } if(m_xteaEncryptionEnabled) - xteaDecrypt(inputMessage); + xteaDecrypt(&m_inputMessage); + + onRecv(&m_inputMessage); } void Protocol::onError(const boost::system::error_code& err) { + std::stringstream message; + logError("PROTOCOL ERROR: ", err.message()); + message << "Boost error: " << err.message(); // invalid hostname // connection timeouted // displays a dialog, finish protocol + + callField("onError", message.str()); } bool Protocol::xteaDecrypt(InputMessage *inputMessage) @@ -163,4 +188,3 @@ uint32 Protocol::getAdlerChecksum(uint8 *buffer, uint16 size) return (b << 16) | a; } - diff --git a/src/framework/net/protocol.h b/src/framework/net/protocol.h index 3a6d86ef..36978452 100644 --- a/src/framework/net/protocol.h +++ b/src/framework/net/protocol.h @@ -38,22 +38,32 @@ //#define RSA "109120132967399429278860960508995541528237502902798129123468757937266291492576446330739696001110603907230888610072655818825358503429057592827629436413108566029093628212635953836686562675849720620786279431090218017681061521755056710823876476444260558147179707119674283982419152118103759076030616683978566631413" +class Protocol; +typedef std::shared_ptr ProtocolPtr; + class Protocol : public LuaObject { public: Protocol(); - void connect(const std::string& host, uint16 port, const std::function& callback); + void connect(const std::string& host, uint16 port); void send(OutputMessage *outputMessage); + void recv(); + void internalRecvHeader(uint8 *buffer, uint16 size); + void internalRecvData(uint8 *buffer, uint16 size); - virtual void onRecv(InputMessage *inputMessage); + virtual void onConnect() = 0; + virtual void onRecv(InputMessage *inputMessage) = 0; virtual void onError(const boost::system::error_code& err); + ProtocolPtr asProtocol() { return std::static_pointer_cast(shared_from_this()); } + virtual const char* getLuaTypeName() const { return "Protocol"; } protected: uint32 m_xteaKey[4]; bool m_xteaEncryptionEnabled; + InputMessage m_inputMessage; private: bool xteaDecrypt(InputMessage *inputMessage); @@ -63,6 +73,4 @@ private: ConnectionPtr m_connection; }; -typedef std::shared_ptr ProtocolPtr; - #endif diff --git a/src/protocollogin.cpp b/src/protocollogin.cpp index 42a06abe..82df6b95 100644 --- a/src/protocollogin.cpp +++ b/src/protocollogin.cpp @@ -41,7 +41,7 @@ void ProtocolLogin::login(const std::string& accountName, const std::string& acc //std::string host = "tecserver.zapto.org"; uint16 port = 7171; - connect(host, port, std::bind(&ProtocolLogin::onConnect, asProtocolLogin())); + connect(host, port); } void ProtocolLogin::onConnect() @@ -55,11 +55,11 @@ void ProtocolLogin::sendPacket() oMsg.addU8(0x01); // Protocol id oMsg.addU16(0x02); // OS - oMsg.addU16(874); // Client version + oMsg.addU16(910); // Client version - oMsg.addU32(0x4DBAA20B); // Data Signature - oMsg.addU32(0x4DAD1A32); // Sprite Signature - oMsg.addU32(0x4DA2D2B5); // Picture Signature + oMsg.addU32(0x4E12DAFF); // Data Signature + oMsg.addU32(0x4E12DB27); // Sprite Signature + oMsg.addU32(0x4E119CBF); // Picture Signature oMsg.addU8(0); // First RSA byte must be 0x00 // 1 @@ -88,12 +88,12 @@ void ProtocolLogin::sendPacket() send(&oMsg); m_xteaEncryptionEnabled = true; + + recv(); } void ProtocolLogin::onRecv(InputMessage *inputMessage) { - Protocol::onRecv(inputMessage); - while(!inputMessage->end()) { uint8 opt = inputMessage->getU8(); logDebug("opt:",(uint)opt);