diff --git a/src/framework/global.h b/src/framework/global.h index d8b7bd9c..252c35db 100644 --- a/src/framework/global.h +++ b/src/framework/global.h @@ -30,6 +30,7 @@ #include #include #include +#include // boost utilities #include diff --git a/src/framework/net/connection.cpp b/src/framework/net/connection.cpp index 8c2a0107..663c3749 100644 --- a/src/framework/net/connection.cpp +++ b/src/framework/net/connection.cpp @@ -42,6 +42,8 @@ void Connection::close() if(!m_connected) return; + m_connected = false; + m_readTimer.cancel(); m_writeTimer.cancel(); @@ -50,16 +52,18 @@ void Connection::close() m_socket.close(); } - m_connected = false; + m_connectCallback = nullptr; + m_errorCallback = nullptr; + m_recvCallback = nullptr; } void Connection::write(uint8* buffer, uint16 size) { + m_writeTimer.cancel(); + if(!m_connected) return; - m_writeTimer.cancel(); - asio::async_write(m_socket, asio::buffer(buffer, size), std::bind(&Connection::onWrite, shared_from_this(), _1, _2)); @@ -102,6 +106,7 @@ void Connection::onResolve(const boost::system::error_code& error, asio::ip::tcp void Connection::onConnect(const boost::system::error_code& error) { m_readTimer.cancel(); + m_connected = true; if(!error) { @@ -115,6 +120,9 @@ void Connection::onWrite(const boost::system::error_code& error, size_t) { m_writeTimer.cancel(); + if(!m_connected) + return; + if(error) handleError(error); } @@ -123,6 +131,9 @@ void Connection::onRecv(const boost::system::error_code& error) { m_readTimer.cancel(); + if(!m_connected) + return; + if(!error) { if(m_recvCallback) g_dispatcher.addEvent(std::bind(m_recvCallback, m_recvBuffer, m_recvSize)); @@ -133,14 +144,16 @@ void Connection::onRecv(const boost::system::error_code& error) void Connection::onTimeout(const boost::system::error_code& error) { if(error != asio::error::operation_aborted) - handleError(error); + handleError(asio::error::timed_out); } void Connection::handleError(const boost::system::error_code& error) { - logTraceDebug(error.message()); - close(); - if(m_errorCallback) - g_dispatcher.addEvent(std::bind(m_errorCallback, error)); + if(error != asio::error::operation_aborted) { + if(m_errorCallback) + g_dispatcher.addEvent(std::bind(m_errorCallback, error)); + if(m_connected) + close(); + } } diff --git a/src/framework/net/protocol.cpp b/src/framework/net/protocol.cpp index f281aa82..5963aa2b 100644 --- a/src/framework/net/protocol.cpp +++ b/src/framework/net/protocol.cpp @@ -1,21 +1,23 @@ #include "protocol.h" #include "connection.h" -Protocol::Protocol() : m_connection(new Connection) +Protocol::Protocol() { - m_connection->setErrorCallback(std::bind(&Protocol::onError, this, _1)); m_xteaEncryptionEnabled = false; - m_checksumEnabled = true; + m_checksumEnabled = false; } void Protocol::connect(const std::string& host, uint16 port) { + m_connection = ConnectionPtr(new Connection); + m_connection->setErrorCallback(std::bind(&Protocol::onError, asProtocol(), _1)); m_connection->connect(host, port, std::bind(&Protocol::onConnect, asProtocol())); } void Protocol::disconnect() { m_connection->close(); + m_connection.reset(); } void Protocol::send(OutputMessage& outputMessage) @@ -76,6 +78,16 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size) onRecv(m_inputMessage); } +void Protocol::generateXteaKey() +{ + std::mt19937 eng(std::time(NULL)); + std::uniform_int_distribution unif(0, 0xFFFFFFFF); + m_xteaKey[0] = unif(eng); + m_xteaKey[1] = unif(eng); + m_xteaKey[2] = unif(eng); + m_xteaKey[3] = unif(eng); +} + bool Protocol::xteaDecrypt(InputMessage& inputMessage) { // FIXME: this function has not been tested yet diff --git a/src/framework/net/protocol.h b/src/framework/net/protocol.h index 7df0e383..112650df 100644 --- a/src/framework/net/protocol.h +++ b/src/framework/net/protocol.h @@ -28,8 +28,11 @@ public: ProtocolPtr asProtocol() { return std::static_pointer_cast(shared_from_this()); } protected: + void enableChecksum() { m_checksumEnabled = true; } + void enableXteaEncryption() { m_xteaEncryptionEnabled = true; } + void generateXteaKey(); + uint32 m_xteaKey[4]; - bool m_checksumEnabled, m_xteaEncryptionEnabled; InputMessage m_inputMessage; private: @@ -37,6 +40,8 @@ private: void xteaEncrypt(OutputMessage& outputMessage); uint32 getAdlerChecksum(uint8* buffer, uint16 size); + bool m_checksumEnabled; + bool m_xteaEncryptionEnabled; ConnectionPtr m_connection; }; diff --git a/src/otclient/core/game.cpp b/src/otclient/core/game.cpp index d7acc9b8..f6fecddf 100644 --- a/src/otclient/core/game.cpp +++ b/src/otclient/core/game.cpp @@ -35,7 +35,10 @@ void Game::onLogin() void Game::onLogout() { - m_protocolGame.reset(); + if(m_protocolGame) { + m_protocolGame->disconnect(); + m_protocolGame.reset(); + } m_localPlayer.reset(); m_online = false; } diff --git a/src/otclient/net/protocolgame.cpp b/src/otclient/net/protocolgame.cpp index 25b83e16..b6d9bd32 100644 --- a/src/otclient/net/protocolgame.cpp +++ b/src/otclient/net/protocolgame.cpp @@ -3,7 +3,6 @@ ProtocolGame::ProtocolGame() { - m_checksumEnabled = false; m_waitingLoginPacket = false; } @@ -38,7 +37,7 @@ void ProtocolGame::onRecv(InputMessage& inputMessage) uint8 unknown = inputMessage.getU8(); m_waitingLoginPacket = false; - m_checksumEnabled = true; + enableChecksum(); sendLoginPacket(timestamp, unknown); recv(); } @@ -50,7 +49,7 @@ void ProtocolGame::onRecv(InputMessage& inputMessage) void ProtocolGame::onError(const boost::system::error_code& error) { - // already disconnected, just send onLogout + // already disconnected, just fire onLogout g_game.onLogout(); } diff --git a/src/otclient/net/protocolgamesend.cpp b/src/otclient/net/protocolgamesend.cpp index 3af0e72b..8021536f 100644 --- a/src/otclient/net/protocolgamesend.cpp +++ b/src/otclient/net/protocolgamesend.cpp @@ -5,42 +5,37 @@ void ProtocolGame::sendLoginPacket(uint32 timestamp, uint8 unknown) { OutputMessage oMsg; - oMsg.addU8(0x0A); // Protocol id - oMsg.addU16(0x02); // OS - oMsg.addU16(862); // Client version + oMsg.addU8(0x0A); // protocol id + oMsg.addU16(0x02); // os + oMsg.addU16(862); // client version - oMsg.addU8(0); // First RSA byte must be 0x00 // 1 + oMsg.addU8(0); // first RSA byte must be 0 - // Generete xtea key. - m_xteaKey[0] = 432324; - m_xteaKey[1] = 24324; - m_xteaKey[2] = 423432; - m_xteaKey[3] = 234324; - - // Add xtea key - oMsg.addU32(m_xteaKey[0]); // 5 - oMsg.addU32(m_xteaKey[1]); // 9 - oMsg.addU32(m_xteaKey[2]); // 13 - oMsg.addU32(m_xteaKey[3]); // 17 + // xtea key + generateXteaKey(); + oMsg.addU32(m_xteaKey[0]); + oMsg.addU32(m_xteaKey[1]); + oMsg.addU32(m_xteaKey[2]); + oMsg.addU32(m_xteaKey[3]); oMsg.addU8(0); // is gm set? - oMsg.addString(m_accountName); // Account Name // 20 - oMsg.addString(m_characterName); // Character Name // 22 - oMsg.addString(m_accountPassword); // Password // 24 + oMsg.addString(m_accountName); + oMsg.addString(m_characterName); + oMsg.addString(m_accountPassword); - oMsg.addU32(timestamp); // 28 - oMsg.addU8(unknown); // 29 + oMsg.addU32(timestamp); + oMsg.addU8(unknown); - // Packet data must have since byte 0, start, 128 bytes + // fill the rest with zeros oMsg.addPaddingBytes(128 - (29 + m_accountName.length() + m_characterName.length() + m_accountPassword.length())); - // Encrypt msg with RSA + // encrypt with RSA if(!Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, OTSERV_PUBLIC_RSA)) return; send(oMsg); - m_xteaEncryptionEnabled = true; + enableXteaEncryption(); } void ProtocolGame::sendLogout() diff --git a/src/otclient/net/protocollogin.cpp b/src/otclient/net/protocollogin.cpp index d4fbce5f..59441fe3 100644 --- a/src/otclient/net/protocollogin.cpp +++ b/src/otclient/net/protocollogin.cpp @@ -10,6 +10,7 @@ ProtocolLogin::ProtocolLogin() { + enableChecksum(); } void ProtocolLogin::login(const std::string& accountName, const std::string& accountPassword) @@ -22,20 +23,6 @@ void ProtocolLogin::login(const std::string& accountName, const std::string& acc m_accountName = accountName; m_accountPassword = accountPassword; - /*static const char hosts[][32] = { - "login01.tibia.com", - "login02.tibia.com", - "login03.tibia.com", - "login04.tibia.com", - "login05.tibia.com", - "tibia01.cipsoft.com", - "tibia02.cipsoft.com", - "tibia03.cipsoft.com", - "tibia04.cipsoft.com", - "tibia05.cipsoft.com" - }; - - std::string host = hosts[rand() % 10];*/ std::string host = "sv3.radbr.com"; uint16 port = 7171; @@ -47,49 +34,6 @@ void ProtocolLogin::onConnect() sendLoginPacket(); } -void ProtocolLogin::sendLoginPacket() -{ - OutputMessage oMsg; - - oMsg.addU8(0x01); // Protocol id - oMsg.addU16(0x02); // OS - oMsg.addU16(862); // Client version - - 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 - - // Generete xtea key. - m_xteaKey[0] = 432324; - m_xteaKey[1] = 24324; - m_xteaKey[2] = 423432; - m_xteaKey[3] = 234324; - - // Add xtea key - oMsg.addU32(m_xteaKey[0]); // 5 - oMsg.addU32(m_xteaKey[1]); // 9 - oMsg.addU32(m_xteaKey[2]); // 13 - oMsg.addU32(m_xteaKey[3]); // 17 - - oMsg.addString(m_accountName); // Account Name // 19 - oMsg.addString(m_accountPassword); // Password // 21 - - // Packet data must have since byte 0, start, 128 bytes - oMsg.addPaddingBytes(128 - (21 + m_accountName.length() + m_accountPassword.length())); - - // Encrypt msg with RSA - if(!Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, OTSERV_PUBLIC_RSA)) - return; - - send(oMsg); - - m_xteaEncryptionEnabled = true; - - recv(); -} - void ProtocolLogin::onRecv(InputMessage& inputMessage) { while(!inputMessage.end()) { @@ -109,19 +53,56 @@ void ProtocolLogin::onRecv(InputMessage& inputMessage) break; } } + disconnect(); } void ProtocolLogin::onError(const boost::system::error_code& error) { - // already disconnected, just send onLogout callLuaField("onError", error.message()); } +void ProtocolLogin::sendLoginPacket() +{ + OutputMessage oMsg; + + oMsg.addU8(0x01); // Protocol id + oMsg.addU16(0x02); // OS + oMsg.addU16(862); // Client version + + 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 + + // Add xtea key + generateXteaKey(); + oMsg.addU32(m_xteaKey[0]); // 5 + oMsg.addU32(m_xteaKey[1]); // 9 + oMsg.addU32(m_xteaKey[2]); // 13 + oMsg.addU32(m_xteaKey[3]); // 17 + + oMsg.addString(m_accountName); // Account Name // 19 + oMsg.addString(m_accountPassword); // Password // 21 + + // Packet data must have since byte 0, start, 128 bytes + oMsg.addPaddingBytes(128 - (21 + m_accountName.length() + m_accountPassword.length())); + + // Encrypt msg with RSA + if(!Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, OTSERV_PUBLIC_RSA)) + return; + + send(oMsg); + + enableXteaEncryption(); + + recv(); +} + void ProtocolLogin::parseError(InputMessage& inputMessage) { std::string error = inputMessage.getString(); callLuaField("onError", error); - disconnect(); } void ProtocolLogin::parseMOTD(InputMessage& inputMessage) @@ -146,5 +127,4 @@ void ProtocolLogin::parseCharacterList(InputMessage& inputMessage) } } /*uint16 premiumDays =*/ inputMessage.getU16(); - disconnect(); } diff --git a/src/otclient/net/protocollogin.h b/src/otclient/net/protocollogin.h index 28ab43c9..ebd0db8a 100644 --- a/src/otclient/net/protocollogin.h +++ b/src/otclient/net/protocollogin.h @@ -15,15 +15,13 @@ public: static ProtocolLoginPtr create() { return ProtocolLoginPtr(new ProtocolLogin); } void login(const std::string& accountName, const std::string& accountPassword); + void cancelLogin() { disconnect(); } void onConnect(); void onRecv(InputMessage& inputMessage); void onError(const boost::system::error_code& error); - void cancel() { /* TODO: this func */ } - ProtocolLoginPtr asProtocolLogin() { return std::static_pointer_cast(shared_from_this()); } - virtual const char* getLuaTypeName() const { return "ProtocolLogin"; } private: void sendLoginPacket(); diff --git a/src/otclient/otclient.cpp b/src/otclient/otclient.cpp index e931bf1f..6f342813 100644 --- a/src/otclient/otclient.cpp +++ b/src/otclient/otclient.cpp @@ -161,7 +161,6 @@ void OTClient::terminate() // terminate network Connection::terminate(); - //g_network.terminate(); // terminate dispatcher g_dispatcher.terminate(); @@ -195,7 +194,6 @@ void OTClient::poll() g_platform.poll(); // poll network events - //g_network.poll(); Connection::poll(); // poll dispatcher events diff --git a/src/otclient/otclientluafunctions.cpp b/src/otclient/otclientluafunctions.cpp index 32689e45..01921c6c 100644 --- a/src/otclient/otclientluafunctions.cpp +++ b/src/otclient/otclientluafunctions.cpp @@ -16,7 +16,7 @@ void OTClient::registerLuaFunctions() g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &ProtocolLogin::create); g_lua.bindClassMemberFunction("login", &ProtocolLogin::login); - g_lua.bindClassMemberFunction("cancel", &ProtocolLogin::cancel); + g_lua.bindClassMemberFunction("cancelLogin", &ProtocolLogin::cancelLogin); g_lua.registerClass(); }