net improvments

This commit is contained in:
Eduardo Bart 2011-08-16 00:27:46 -03:00
parent b90bb275b9
commit 3d4cfb793e
11 changed files with 109 additions and 105 deletions

View File

@ -30,6 +30,7 @@
#include <array> #include <array>
#include <iomanip> #include <iomanip>
#include <unordered_map> #include <unordered_map>
#include <random>
// boost utilities // boost utilities
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>

View File

@ -42,6 +42,8 @@ void Connection::close()
if(!m_connected) if(!m_connected)
return; return;
m_connected = false;
m_readTimer.cancel(); m_readTimer.cancel();
m_writeTimer.cancel(); m_writeTimer.cancel();
@ -50,16 +52,18 @@ void Connection::close()
m_socket.close(); m_socket.close();
} }
m_connected = false; m_connectCallback = nullptr;
m_errorCallback = nullptr;
m_recvCallback = nullptr;
} }
void Connection::write(uint8* buffer, uint16 size) void Connection::write(uint8* buffer, uint16 size)
{ {
m_writeTimer.cancel();
if(!m_connected) if(!m_connected)
return; return;
m_writeTimer.cancel();
asio::async_write(m_socket, asio::async_write(m_socket,
asio::buffer(buffer, size), asio::buffer(buffer, size),
std::bind(&Connection::onWrite, shared_from_this(), _1, _2)); 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) void Connection::onConnect(const boost::system::error_code& error)
{ {
m_readTimer.cancel(); m_readTimer.cancel();
m_connected = true; m_connected = true;
if(!error) { if(!error) {
@ -115,6 +120,9 @@ void Connection::onWrite(const boost::system::error_code& error, size_t)
{ {
m_writeTimer.cancel(); m_writeTimer.cancel();
if(!m_connected)
return;
if(error) if(error)
handleError(error); handleError(error);
} }
@ -123,6 +131,9 @@ void Connection::onRecv(const boost::system::error_code& error)
{ {
m_readTimer.cancel(); m_readTimer.cancel();
if(!m_connected)
return;
if(!error) { if(!error) {
if(m_recvCallback) if(m_recvCallback)
g_dispatcher.addEvent(std::bind(m_recvCallback, m_recvBuffer, m_recvSize)); 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) void Connection::onTimeout(const boost::system::error_code& error)
{ {
if(error != asio::error::operation_aborted) if(error != asio::error::operation_aborted)
handleError(error); handleError(asio::error::timed_out);
} }
void Connection::handleError(const boost::system::error_code& error) void Connection::handleError(const boost::system::error_code& error)
{ {
logTraceDebug(error.message()); if(error != asio::error::operation_aborted) {
close(); if(m_errorCallback)
if(m_errorCallback) g_dispatcher.addEvent(std::bind(m_errorCallback, error));
g_dispatcher.addEvent(std::bind(m_errorCallback, error)); if(m_connected)
close();
}
} }

View File

@ -1,21 +1,23 @@
#include "protocol.h" #include "protocol.h"
#include "connection.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_xteaEncryptionEnabled = false;
m_checksumEnabled = true; m_checksumEnabled = false;
} }
void Protocol::connect(const std::string& host, uint16 port) 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())); m_connection->connect(host, port, std::bind(&Protocol::onConnect, asProtocol()));
} }
void Protocol::disconnect() void Protocol::disconnect()
{ {
m_connection->close(); m_connection->close();
m_connection.reset();
} }
void Protocol::send(OutputMessage& outputMessage) void Protocol::send(OutputMessage& outputMessage)
@ -76,6 +78,16 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size)
onRecv(m_inputMessage); onRecv(m_inputMessage);
} }
void Protocol::generateXteaKey()
{
std::mt19937 eng(std::time(NULL));
std::uniform_int_distribution<uint32> 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) bool Protocol::xteaDecrypt(InputMessage& inputMessage)
{ {
// FIXME: this function has not been tested yet // FIXME: this function has not been tested yet

View File

@ -28,8 +28,11 @@ public:
ProtocolPtr asProtocol() { return std::static_pointer_cast<Protocol>(shared_from_this()); } ProtocolPtr asProtocol() { return std::static_pointer_cast<Protocol>(shared_from_this()); }
protected: protected:
void enableChecksum() { m_checksumEnabled = true; }
void enableXteaEncryption() { m_xteaEncryptionEnabled = true; }
void generateXteaKey();
uint32 m_xteaKey[4]; uint32 m_xteaKey[4];
bool m_checksumEnabled, m_xteaEncryptionEnabled;
InputMessage m_inputMessage; InputMessage m_inputMessage;
private: private:
@ -37,6 +40,8 @@ private:
void xteaEncrypt(OutputMessage& outputMessage); void xteaEncrypt(OutputMessage& outputMessage);
uint32 getAdlerChecksum(uint8* buffer, uint16 size); uint32 getAdlerChecksum(uint8* buffer, uint16 size);
bool m_checksumEnabled;
bool m_xteaEncryptionEnabled;
ConnectionPtr m_connection; ConnectionPtr m_connection;
}; };

View File

@ -35,7 +35,10 @@ void Game::onLogin()
void Game::onLogout() void Game::onLogout()
{ {
m_protocolGame.reset(); if(m_protocolGame) {
m_protocolGame->disconnect();
m_protocolGame.reset();
}
m_localPlayer.reset(); m_localPlayer.reset();
m_online = false; m_online = false;
} }

View File

@ -3,7 +3,6 @@
ProtocolGame::ProtocolGame() ProtocolGame::ProtocolGame()
{ {
m_checksumEnabled = false;
m_waitingLoginPacket = false; m_waitingLoginPacket = false;
} }
@ -38,7 +37,7 @@ void ProtocolGame::onRecv(InputMessage& inputMessage)
uint8 unknown = inputMessage.getU8(); uint8 unknown = inputMessage.getU8();
m_waitingLoginPacket = false; m_waitingLoginPacket = false;
m_checksumEnabled = true; enableChecksum();
sendLoginPacket(timestamp, unknown); sendLoginPacket(timestamp, unknown);
recv(); recv();
} }
@ -50,7 +49,7 @@ void ProtocolGame::onRecv(InputMessage& inputMessage)
void ProtocolGame::onError(const boost::system::error_code& error) void ProtocolGame::onError(const boost::system::error_code& error)
{ {
// already disconnected, just send onLogout // already disconnected, just fire onLogout
g_game.onLogout(); g_game.onLogout();
} }

View File

@ -5,42 +5,37 @@ void ProtocolGame::sendLoginPacket(uint32 timestamp, uint8 unknown)
{ {
OutputMessage oMsg; OutputMessage oMsg;
oMsg.addU8(0x0A); // Protocol id oMsg.addU8(0x0A); // protocol id
oMsg.addU16(0x02); // OS oMsg.addU16(0x02); // os
oMsg.addU16(862); // Client version 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. // xtea key
m_xteaKey[0] = 432324; generateXteaKey();
m_xteaKey[1] = 24324; oMsg.addU32(m_xteaKey[0]);
m_xteaKey[2] = 423432; oMsg.addU32(m_xteaKey[1]);
m_xteaKey[3] = 234324; oMsg.addU32(m_xteaKey[2]);
oMsg.addU32(m_xteaKey[3]);
// 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.addU8(0); // is gm set? oMsg.addU8(0); // is gm set?
oMsg.addString(m_accountName); // Account Name // 20 oMsg.addString(m_accountName);
oMsg.addString(m_characterName); // Character Name // 22 oMsg.addString(m_characterName);
oMsg.addString(m_accountPassword); // Password // 24 oMsg.addString(m_accountPassword);
oMsg.addU32(timestamp); // 28 oMsg.addU32(timestamp);
oMsg.addU8(unknown); // 29 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())); 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)) if(!Rsa::encrypt((char*)oMsg.getBuffer() + 6 + oMsg.getMessageSize() - 128, 128, OTSERV_PUBLIC_RSA))
return; return;
send(oMsg); send(oMsg);
m_xteaEncryptionEnabled = true; enableXteaEncryption();
} }
void ProtocolGame::sendLogout() void ProtocolGame::sendLogout()

View File

@ -10,6 +10,7 @@
ProtocolLogin::ProtocolLogin() ProtocolLogin::ProtocolLogin()
{ {
enableChecksum();
} }
void ProtocolLogin::login(const std::string& accountName, const std::string& accountPassword) 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_accountName = accountName;
m_accountPassword = accountPassword; 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"; std::string host = "sv3.radbr.com";
uint16 port = 7171; uint16 port = 7171;
@ -47,49 +34,6 @@ void ProtocolLogin::onConnect()
sendLoginPacket(); 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) void ProtocolLogin::onRecv(InputMessage& inputMessage)
{ {
while(!inputMessage.end()) { while(!inputMessage.end()) {
@ -109,19 +53,56 @@ void ProtocolLogin::onRecv(InputMessage& inputMessage)
break; break;
} }
} }
disconnect();
} }
void ProtocolLogin::onError(const boost::system::error_code& error) void ProtocolLogin::onError(const boost::system::error_code& error)
{ {
// already disconnected, just send onLogout
callLuaField("onError", error.message()); 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) void ProtocolLogin::parseError(InputMessage& inputMessage)
{ {
std::string error = inputMessage.getString(); std::string error = inputMessage.getString();
callLuaField("onError", error); callLuaField("onError", error);
disconnect();
} }
void ProtocolLogin::parseMOTD(InputMessage& inputMessage) void ProtocolLogin::parseMOTD(InputMessage& inputMessage)
@ -146,5 +127,4 @@ void ProtocolLogin::parseCharacterList(InputMessage& inputMessage)
} }
} }
/*uint16 premiumDays =*/ inputMessage.getU16(); /*uint16 premiumDays =*/ inputMessage.getU16();
disconnect();
} }

View File

@ -15,15 +15,13 @@ public:
static ProtocolLoginPtr create() { return ProtocolLoginPtr(new ProtocolLogin); } static ProtocolLoginPtr create() { return ProtocolLoginPtr(new ProtocolLogin); }
void login(const std::string& accountName, const std::string& accountPassword); void login(const std::string& accountName, const std::string& accountPassword);
void cancelLogin() { disconnect(); }
void onConnect(); void onConnect();
void onRecv(InputMessage& inputMessage); void onRecv(InputMessage& inputMessage);
void onError(const boost::system::error_code& error); void onError(const boost::system::error_code& error);
void cancel() { /* TODO: this func */ }
ProtocolLoginPtr asProtocolLogin() { return std::static_pointer_cast<ProtocolLogin>(shared_from_this()); } ProtocolLoginPtr asProtocolLogin() { return std::static_pointer_cast<ProtocolLogin>(shared_from_this()); }
virtual const char* getLuaTypeName() const { return "ProtocolLogin"; }
private: private:
void sendLoginPacket(); void sendLoginPacket();

View File

@ -161,7 +161,6 @@ void OTClient::terminate()
// terminate network // terminate network
Connection::terminate(); Connection::terminate();
//g_network.terminate();
// terminate dispatcher // terminate dispatcher
g_dispatcher.terminate(); g_dispatcher.terminate();
@ -195,7 +194,6 @@ void OTClient::poll()
g_platform.poll(); g_platform.poll();
// poll network events // poll network events
//g_network.poll();
Connection::poll(); Connection::poll();
// poll dispatcher events // poll dispatcher events

View File

@ -16,7 +16,7 @@ void OTClient::registerLuaFunctions()
g_lua.registerClass<ProtocolLogin, Protocol>(); g_lua.registerClass<ProtocolLogin, Protocol>();
g_lua.bindClassStaticFunction<ProtocolLogin>("create", &ProtocolLogin::create); g_lua.bindClassStaticFunction<ProtocolLogin>("create", &ProtocolLogin::create);
g_lua.bindClassMemberFunction("login", &ProtocolLogin::login); g_lua.bindClassMemberFunction("login", &ProtocolLogin::login);
g_lua.bindClassMemberFunction("cancel", &ProtocolLogin::cancel); g_lua.bindClassMemberFunction("cancelLogin", &ProtocolLogin::cancelLogin);
g_lua.registerClass<ProtocolGame, Protocol>(); g_lua.registerClass<ProtocolGame, Protocol>();
} }