add lua flexibility for protocol

* use shared_ptr for InputMessage and OutputMessage and bind them
* allow sending network messages from lua
* implement extended opcode
* use own OS type  for otclient to allow server side detection
* fixes in input event bot protection
* move RSA to input/output network messages
* allow to capture opcodes before GameProtocol parsing with the event GameProtocol.onOpcode
* fixes in lua std::string pop/push to allow byte buffering
This commit is contained in:
Eduardo Bart 2012-05-14 18:36:54 -03:00
parent e7030a4995
commit 2478809945
26 changed files with 969 additions and 938 deletions

View File

@ -221,8 +221,10 @@ void Application::poll()
void Application::close() void Application::close()
{ {
m_onInputEvent = true;
if(!g_lua.callGlobalField<bool>("g_app", "onClose")) if(!g_lua.callGlobalField<bool>("g_app", "onClose"))
exit(); exit();
m_onInputEvent = false;
} }
void Application::render() void Application::render()
@ -235,11 +237,15 @@ void Application::render()
void Application::resize(const Size& size) void Application::resize(const Size& size)
{ {
m_onInputEvent = true;
g_graphics.resize(size); g_graphics.resize(size);
g_ui.resize(size); g_ui.resize(size);
m_onInputEvent = false;
} }
void Application::inputEvent(const InputEvent& event) void Application::inputEvent(const InputEvent& event)
{ {
m_onInputEvent = true;
g_ui.inputEvent(event); g_ui.inputEvent(event);
m_onInputEvent = false;
} }

View File

@ -47,6 +47,7 @@ public:
bool isRunning() { return m_running; } bool isRunning() { return m_running; }
bool isStopping() { return m_stopping; } bool isStopping() { return m_stopping; }
bool isOnInputEvent() { return m_onInputEvent; }
int getFrameSleep() { return m_frameSleep; } int getFrameSleep() { return m_frameSleep; }
const std::string& getName() { return m_appName; } const std::string& getName() { return m_appName; }
const std::string& getVersion() { return m_appVersion; } const std::string& getVersion() { return m_appVersion; }
@ -68,6 +69,7 @@ protected:
Boolean<false> m_initialized; Boolean<false> m_initialized;
Boolean<false> m_running; Boolean<false> m_running;
Boolean<false> m_stopping; Boolean<false> m_stopping;
Boolean<false> m_onInputEvent;
}; };
extern Application *g_app; extern Application *g_app;

View File

@ -397,6 +397,11 @@ void Application::registerLuaFunctions()
// Protocol // Protocol
g_lua.registerClass<Protocol>(); g_lua.registerClass<Protocol>();
//g_lua.bindClassMemberFunction<Protocol>("connect", &Protocol::connect);
g_lua.bindClassMemberFunction<Protocol>("disconnect", &Protocol::disconnect);
g_lua.bindClassMemberFunction<Protocol>("isConnected", &Protocol::isConnected);
g_lua.bindClassMemberFunction<Protocol>("isConnecting", &Protocol::isConnecting);
g_lua.bindClassMemberFunction<Protocol>("send", &Protocol::send);
// Module // Module
g_lua.registerClass<Module>(); g_lua.registerClass<Module>();
@ -415,20 +420,31 @@ void Application::registerLuaFunctions()
g_lua.bindClassMemberFunction<Module>("isAutoLoad", &Module::isAutoLoad); g_lua.bindClassMemberFunction<Module>("isAutoLoad", &Module::isAutoLoad);
g_lua.bindClassMemberFunction<Module>("getAutoLoadPriority", &Module::getAutoLoadPriority); g_lua.bindClassMemberFunction<Module>("getAutoLoadPriority", &Module::getAutoLoadPriority);
// network manipulation via lua is disabled for a while // InputMessage
/* g_lua.registerClass<InputMessage>();
g_lua.bindClassStaticFunction<InputMessage>("create", []{ return InputMessagePtr(new InputMessage); });
g_lua.bindClassMemberFunction<InputMessage>("skipBytes", &InputMessage::skipBytes);
g_lua.bindClassMemberFunction<InputMessage>("getU8", &InputMessage::getU8);
g_lua.bindClassMemberFunction<InputMessage>("getU16", &InputMessage::getU16);
g_lua.bindClassMemberFunction<InputMessage>("getU32", &InputMessage::getU32);
g_lua.bindClassMemberFunction<InputMessage>("getU64", &InputMessage::getU64);
g_lua.bindClassMemberFunction<InputMessage>("getString", &InputMessage::getString);
g_lua.bindClassMemberFunction<InputMessage>("decryptRSA", &InputMessage::decryptRSA);
g_lua.bindClassMemberFunction<InputMessage>("getReadSize", &InputMessage::getReadSize);
g_lua.bindClassMemberFunction<InputMessage>("getUnreadSize", &InputMessage::getUnreadSize);
g_lua.bindClassMemberFunction<InputMessage>("eof", &InputMessage::eof);
// OutputMessage // OutputMessage
g_lua.registerClass<OutputMessage>(); g_lua.registerClass<OutputMessage>();
g_lua.bindClassStaticFunction<OutputMessage>("new", []{ return OutputMessagePtr(new OutputMessage); }); g_lua.bindClassStaticFunction<OutputMessage>("create", []{ return OutputMessagePtr(new OutputMessage); });
g_lua.bindClassMemberFunction<OutputMessage>("reset", &OutputMessage::reset); g_lua.bindClassMemberFunction<OutputMessage>("reset", &OutputMessage::reset);
g_lua.bindClassMemberFunction<OutputMessage>("addU8", &OutputMessage::addU8); g_lua.bindClassMemberFunction<OutputMessage>("addU8", &OutputMessage::addU8);
g_lua.bindClassMemberFunction<OutputMessage>("addU16", &OutputMessage::addU16); g_lua.bindClassMemberFunction<OutputMessage>("addU16", &OutputMessage::addU16);
g_lua.bindClassMemberFunction<OutputMessage>("addU32", &OutputMessage::addU32); g_lua.bindClassMemberFunction<OutputMessage>("addU32", &OutputMessage::addU32);
g_lua.bindClassMemberFunction<OutputMessage>("addU64", &OutputMessage::addU64); g_lua.bindClassMemberFunction<OutputMessage>("addU64", &OutputMessage::addU64);
g_lua.bindClassMemberFunction<OutputMessage>("addString", (void(OutputMessage::*)(const std::string&))&OutputMessage::addString); g_lua.bindClassMemberFunction<OutputMessage>("addString", &OutputMessage::addString);
g_lua.bindClassMemberFunction<OutputMessage>("addPaddingBytes", &OutputMessage::addPaddingBytes);
g_lua.bindClassStaticFunction<Protocol>("send", [](const ProtocolPtr proto, OutputMessagePtr msg) { proto->send(*msg.get()); }); g_lua.bindClassMemberFunction<OutputMessage>("encryptRSA", &OutputMessage::encryptRSA);
*/
// Application // Application
g_lua.registerStaticClass("g_app"); g_lua.registerStaticClass("g_app");

View File

@ -610,7 +610,7 @@ void LuaInterface::createLuaState()
// load lua standard libraries // load lua standard libraries
luaL_openlibs(L); luaL_openlibs(L);
// load bit32 lib for bitwise operations // load bit32 lib for bitwise operations
luaopen_bit32(L); luaopen_bit32(L);
@ -998,6 +998,11 @@ void LuaInterface::pushCString(const char* v)
lua_pushstring(L, v); lua_pushstring(L, v);
} }
void LuaInterface::pushString(const std::string& v)
{
lua_pushlstring(L, v.c_str(), v.length());
}
void LuaInterface::pushLightUserdata(void* p) void LuaInterface::pushLightUserdata(void* p)
{ {
lua_pushlightuserdata(L, p); lua_pushlightuserdata(L, p);
@ -1121,9 +1126,10 @@ std::string LuaInterface::toString(int index)
{ {
assert(hasIndex(index)); assert(hasIndex(index));
std::string str; std::string str;
const char *c_str = lua_tostring(L, index); size_t len;
if(c_str) const char *c_str = lua_tolstring(L, index, &len);
str = c_str; if(c_str && len > 0)
str.assign(c_str, len);
return str; return str;
} }

View File

@ -269,7 +269,7 @@ public:
void pushNumber(double v); void pushNumber(double v);
void pushBoolean(bool v); void pushBoolean(bool v);
void pushCString(const char* v); void pushCString(const char* v);
void pushString(const std::string& v) { pushCString(v.c_str()); } void pushString(const std::string& v);
void pushLightUserdata(void* p); void pushLightUserdata(void* p);
void pushThread(); void pushThread();
void pushValue(int index = -1); void pushValue(int index = -1);

View File

@ -28,12 +28,14 @@
namespace asio = boost::asio; namespace asio = boost::asio;
class Connection;
class InputMessage; class InputMessage;
class OutputMessage; class OutputMessage;
class Connection;
class Protocol; class Protocol;
class Server; class Server;
typedef std::shared_ptr<InputMessage> InputMessagePtr;
typedef std::shared_ptr<OutputMessage> OutputMessagePtr;
typedef std::shared_ptr<Connection> ConnectionPtr; typedef std::shared_ptr<Connection> ConnectionPtr;
typedef std::weak_ptr<Connection> ConnectionWeakPtr; typedef std::weak_ptr<Connection> ConnectionWeakPtr;
typedef std::shared_ptr<Protocol> ProtocolPtr; typedef std::shared_ptr<Protocol> ProtocolPtr;

View File

@ -21,6 +21,7 @@
*/ */
#include "inputmessage.h" #include "inputmessage.h"
#include "rsa.h"
InputMessage::InputMessage() InputMessage::InputMessage()
{ {
@ -106,6 +107,11 @@ std::string InputMessage::getString()
return std::string(v, stringLength); return std::string(v, stringLength);
} }
void InputMessage::decryptRSA(int size, const std::string& p, const std::string& q, const std::string& d)
{
RSA::decrypt((char*)m_buffer + m_readPos, size, p.c_str(), q.c_str(), d.c_str());
}
bool InputMessage::canRead(int bytes) bool InputMessage::canRead(int bytes)
{ {
if((m_readPos - m_headerPos + bytes > m_messageSize) || (m_readPos + bytes > BUFFER_MAXSIZE)) if((m_readPos - m_headerPos + bytes > m_messageSize) || (m_readPos + bytes > BUFFER_MAXSIZE))

View File

@ -25,8 +25,9 @@
#include "declarations.h" #include "declarations.h"
#include "networkexception.h" #include "networkexception.h"
#include <framework/luascript/luaobject.h>
class InputMessage class InputMessage : public LuaObject
{ {
public: public:
enum { enum {
@ -36,32 +37,38 @@ public:
InputMessage(); InputMessage();
void reset();
void fillBuffer(uint8 *buffer, uint16 size);
uint16 readSize() { return getU16(); }
bool readChecksum();
void setHeaderSize(uint16 size);
void setMessageSize(uint16 size) { m_messageSize = size; }
void skipBytes(uint16 bytes) { m_readPos += bytes; } void skipBytes(uint16 bytes) { m_readPos += bytes; }
uint8 getU8(bool peek = false); uint8 getU8(bool peek = false);
uint16 getU16(bool peek = false); uint16 getU16(bool peek = false);
uint32 getU32(bool peek = false); uint32 getU32(bool peek = false);
uint64 getU64(bool peek = false); uint64 getU64(bool peek = false);
std::string getString(); std::string getString();
void decryptRSA(int size, const std::string& p, const std::string& q, const std::string& d);
int getReadSize() { return m_readPos - m_headerPos; }
int getUnreadSize() { return m_messageSize - (m_readPos - m_headerPos); }
bool eof() { return (m_readPos - m_headerPos) >= m_messageSize; }
protected:
void reset();
void fillBuffer(uint8 *buffer, uint16 size);
void setHeaderSize(uint16 size);
void setMessageSize(uint16 size) { m_messageSize = size; }
uint8* getReadBuffer() { return m_buffer + m_readPos; } uint8* getReadBuffer() { return m_buffer + m_readPos; }
uint8* getHeaderBuffer() { return m_buffer + m_headerPos; } uint8* getHeaderBuffer() { return m_buffer + m_headerPos; }
uint8* getDataBuffer() { return m_buffer + MAX_HEADER_SIZE; } uint8* getDataBuffer() { return m_buffer + MAX_HEADER_SIZE; }
uint16 getHeaderSize() { return (MAX_HEADER_SIZE - m_headerPos); } uint16 getHeaderSize() { return (MAX_HEADER_SIZE - m_headerPos); }
uint16 getMessageSize() { return m_messageSize; } uint16 getMessageSize() { return m_messageSize; }
int getReadSize() { return m_readPos - m_headerPos; }
int getUnreadSize() { return m_messageSize - (m_readPos - m_headerPos); }
bool eof() { return (m_readPos - m_headerPos) >= m_messageSize; } uint16 readSize() { return getU16(); }
bool readChecksum();
friend class Protocol;
private: private:
bool canRead(int bytes); bool canRead(int bytes);

View File

@ -21,6 +21,7 @@
*/ */
#include <framework/net/outputmessage.h> #include <framework/net/outputmessage.h>
#include "rsa.h"
OutputMessage::OutputMessage() OutputMessage::OutputMessage()
{ {
@ -66,20 +67,16 @@ void OutputMessage::addU64(uint64 value)
m_messageSize += 8; m_messageSize += 8;
} }
void OutputMessage::addString(const char* value, int length) void OutputMessage::addString(const std::string& buffer)
{ {
if(length > 65535) int len = buffer.length();
throw NetworkException("[OutputMessage::addString] string length > 65535"); if(len > MAX_STRING_LENGTH)
checkWrite(length + 2); throw NetworkException("string length > MAX_STRING_LENGTH");
addU16(length); checkWrite(len + 2);
memcpy((char*)(m_buffer + m_writePos), value, length); addU16(len);
m_writePos += length; memcpy((char*)(m_buffer + m_writePos), buffer.c_str(), len);
m_messageSize += length; m_writePos += len;
} m_messageSize += len;
void OutputMessage::addString(const std::string& value)
{
addString(value.c_str(), value.length());
} }
void OutputMessage::addPaddingBytes(int bytes, uint8 byte) void OutputMessage::addPaddingBytes(int bytes, uint8 byte)
@ -92,6 +89,11 @@ void OutputMessage::addPaddingBytes(int bytes, uint8 byte)
m_messageSize += bytes; m_messageSize += bytes;
} }
void OutputMessage::encryptRSA(int size, const std::string& key)
{
RSA::encrypt((char*)m_buffer + m_writePos - size, size, key.c_str());
}
void OutputMessage::writeChecksum() void OutputMessage::writeChecksum()
{ {
uint32 checksum = Fw::getAdlerChecksum(m_buffer + m_headerPos, m_messageSize); uint32 checksum = Fw::getAdlerChecksum(m_buffer + m_headerPos, m_messageSize);

View File

@ -27,13 +27,12 @@
#include "networkexception.h" #include "networkexception.h"
#include <framework/luascript/luaobject.h> #include <framework/luascript/luaobject.h>
typedef std::shared_ptr<OutputMessage> OutputMessagePtr;
class OutputMessage : public LuaObject class OutputMessage : public LuaObject
{ {
public: public:
enum { enum {
BUFFER_MAXSIZE = 1024, BUFFER_MAXSIZE = 1024,
MAX_STRING_LENGTH = 65536,
MAX_HEADER_SIZE = 8 MAX_HEADER_SIZE = 8
}; };
@ -45,10 +44,12 @@ public:
void addU16(uint16 value); void addU16(uint16 value);
void addU32(uint32 value); void addU32(uint32 value);
void addU64(uint64 value); void addU64(uint64 value);
void addString(const char* value, int length); void addString(const std::string& buffer);
void addString(const std::string& value);
void addPaddingBytes(int bytes, uint8 byte = 0); void addPaddingBytes(int bytes, uint8 byte = 0);
void encryptRSA(int size, const std::string& key);
protected:
uint8* getWriteBuffer() { return m_buffer + m_writePos; } uint8* getWriteBuffer() { return m_buffer + m_writePos; }
uint8* getHeaderBuffer() { return m_buffer + m_headerPos; } uint8* getHeaderBuffer() { return m_buffer + m_headerPos; }
uint8* getDataBuffer() { return m_buffer + MAX_HEADER_SIZE; } uint8* getDataBuffer() { return m_buffer + MAX_HEADER_SIZE; }
@ -57,6 +58,8 @@ public:
void writeChecksum(); void writeChecksum();
void writeMessageSize(); void writeMessageSize();
friend class Protocol;
private: private:
bool canWrite(int bytes); bool canWrite(int bytes);
void checkWrite(int bytes); void checkWrite(int bytes);

View File

@ -27,6 +27,7 @@ Protocol::Protocol()
{ {
m_xteaEncryptionEnabled = false; m_xteaEncryptionEnabled = false;
m_checksumEnabled = false; m_checksumEnabled = false;
m_inputMessage = InputMessagePtr(new InputMessage);
} }
Protocol::~Protocol() Protocol::~Protocol()
@ -63,7 +64,7 @@ bool Protocol::isConnecting()
return false; return false;
} }
void Protocol::send(OutputMessage& outputMessage) void Protocol::send(const OutputMessagePtr& outputMessage)
{ {
// encrypt // encrypt
if(m_xteaEncryptionEnabled) if(m_xteaEncryptionEnabled)
@ -71,19 +72,19 @@ void Protocol::send(OutputMessage& outputMessage)
// write checksum // write checksum
if(m_checksumEnabled) if(m_checksumEnabled)
outputMessage.writeChecksum(); outputMessage->writeChecksum();
// wirte message size // wirte message size
outputMessage.writeMessageSize(); outputMessage->writeMessageSize();
// send // send
if(m_connection) if(m_connection)
m_connection->write(outputMessage.getHeaderBuffer(), outputMessage.getMessageSize()); m_connection->write(outputMessage->getHeaderBuffer(), outputMessage->getMessageSize());
} }
void Protocol::recv() void Protocol::recv()
{ {
m_inputMessage.reset(); m_inputMessage->reset();
// first update message header size // first update message header size
int headerSize = 2; // 2 bytes for message size int headerSize = 2; // 2 bytes for message size
@ -91,7 +92,7 @@ void Protocol::recv()
headerSize += 4; // 4 bytes for checksum headerSize += 4; // 4 bytes for checksum
if(m_xteaEncryptionEnabled) if(m_xteaEncryptionEnabled)
headerSize += 2; // 2 bytes for XTEA encrypted message size headerSize += 2; // 2 bytes for XTEA encrypted message size
m_inputMessage.setHeaderSize(headerSize); m_inputMessage->setHeaderSize(headerSize);
// read the first 2 bytes which contain the message size // read the first 2 bytes which contain the message size
if(m_connection) if(m_connection)
@ -101,8 +102,8 @@ void Protocol::recv()
void Protocol::internalRecvHeader(uint8* buffer, uint16 size) void Protocol::internalRecvHeader(uint8* buffer, uint16 size)
{ {
// read message size // read message size
m_inputMessage.fillBuffer(buffer, size); m_inputMessage->fillBuffer(buffer, size);
uint16 remainingSize = m_inputMessage.readSize(); uint16 remainingSize = m_inputMessage->readSize();
// read remaining message data // read remaining message data
if(m_connection) if(m_connection)
@ -117,9 +118,9 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size)
return; return;
} }
m_inputMessage.fillBuffer(buffer, size); m_inputMessage->fillBuffer(buffer, size);
if(m_checksumEnabled && !m_inputMessage.readChecksum()) { if(m_checksumEnabled && !m_inputMessage->readChecksum()) {
logTraceError("got a network message with invalid checksum"); logTraceError("got a network message with invalid checksum");
return; return;
} }
@ -130,8 +131,8 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size)
return; return;
} }
} else { } else {
int size = m_inputMessage.getU16(); int size = m_inputMessage->getU16();
if(size != m_inputMessage.getUnreadSize()) { if(size != m_inputMessage->getUnreadSize()) {
logTraceError("invalid message size"); logTraceError("invalid message size");
return; return;
} }
@ -150,15 +151,15 @@ void Protocol::generateXteaKey()
m_xteaKey[3] = unif(eng); m_xteaKey[3] = unif(eng);
} }
bool Protocol::xteaDecrypt(InputMessage& inputMessage) bool Protocol::xteaDecrypt(const InputMessagePtr& inputMessage)
{ {
uint16 encryptedSize = inputMessage.getUnreadSize(); uint16 encryptedSize = inputMessage->getUnreadSize();
if(encryptedSize % 8 != 0) { if(encryptedSize % 8 != 0) {
logTraceError("invalid encrypted network message"); logTraceError("invalid encrypted network message");
return false; return false;
} }
uint32 *buffer = (uint32*)(inputMessage.getReadBuffer()); uint32 *buffer = (uint32*)(inputMessage->getReadBuffer());
int readPos = 0; int readPos = 0;
while(readPos < encryptedSize/4) { while(readPos < encryptedSize/4) {
@ -175,31 +176,31 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage)
readPos = readPos + 2; readPos = readPos + 2;
} }
uint16 decryptedSize = inputMessage.getU16() + 2; uint16 decryptedSize = inputMessage->getU16() + 2;
int sizeDelta = decryptedSize - encryptedSize; int sizeDelta = decryptedSize - encryptedSize;
if(sizeDelta > 0 || -sizeDelta > encryptedSize) { if(sizeDelta > 0 || -sizeDelta > encryptedSize) {
logTraceError("invalid decrypted a network message"); logTraceError("invalid decrypted a network message");
return false; return false;
} }
inputMessage.setMessageSize(inputMessage.getMessageSize() + sizeDelta); inputMessage->setMessageSize(inputMessage->getMessageSize() + sizeDelta);
return true; return true;
} }
void Protocol::xteaEncrypt(OutputMessage& outputMessage) void Protocol::xteaEncrypt(const OutputMessagePtr& outputMessage)
{ {
outputMessage.writeMessageSize(); outputMessage->writeMessageSize();
uint16 encryptedSize = outputMessage.getMessageSize(); uint16 encryptedSize = outputMessage->getMessageSize();
//add bytes until reach 8 multiple //add bytes until reach 8 multiple
if((encryptedSize % 8) != 0) { if((encryptedSize % 8) != 0) {
uint16 n = 8 - (encryptedSize % 8); uint16 n = 8 - (encryptedSize % 8);
outputMessage.addPaddingBytes(n); outputMessage->addPaddingBytes(n);
encryptedSize += n; encryptedSize += n;
} }
int readPos = 0; int readPos = 0;
uint32 *buffer = (uint32*)(outputMessage.getDataBuffer() - 2); uint32 *buffer = (uint32*)(outputMessage->getDataBuffer() - 2);
while(readPos < encryptedSize / 4) { while(readPos < encryptedSize / 4) {
uint32 v0 = buffer[readPos], v1 = buffer[readPos + 1]; uint32 v0 = buffer[readPos], v1 = buffer[readPos + 1];
uint32 delta = 0x61C88647; uint32 delta = 0x61C88647;

View File

@ -41,33 +41,34 @@ public:
bool isConnected(); bool isConnected();
bool isConnecting(); bool isConnecting();
void send(OutputMessage& outputMessage); virtual void send(const OutputMessagePtr& outputMessage);
void recv();
void internalRecvHeader(uint8* buffer, uint16 size);
void internalRecvData(uint8* buffer, uint16 size);
virtual void onConnect() = 0;
virtual void onRecv(InputMessage& inputMessage) = 0;
virtual void onError(const boost::system::error_code& err) = 0;
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 recv();
virtual void onConnect() = 0;
virtual void onRecv(const InputMessagePtr& inputMessage) = 0;
virtual void onError(const boost::system::error_code& err) = 0;
void enableChecksum() { m_checksumEnabled = true; } void enableChecksum() { m_checksumEnabled = true; }
void enableXteaEncryption() { m_xteaEncryptionEnabled = true; } void enableXteaEncryption() { m_xteaEncryptionEnabled = true; }
void generateXteaKey(); void generateXteaKey();
uint32 m_xteaKey[4]; uint32 m_xteaKey[4];
InputMessage m_inputMessage;
private: private:
bool xteaDecrypt(InputMessage& inputMessage); void internalRecvHeader(uint8* buffer, uint16 size);
void xteaEncrypt(OutputMessage& outputMessage); void internalRecvData(uint8* buffer, uint16 size);
bool xteaDecrypt(const InputMessagePtr& inputMessage);
void xteaEncrypt(const OutputMessagePtr& outputMessage);
bool m_checksumEnabled; bool m_checksumEnabled;
bool m_xteaEncryptionEnabled; bool m_xteaEncryptionEnabled;
ConnectionPtr m_connection; ConnectionPtr m_connection;
InputMessagePtr m_inputMessage;
}; };
#endif #endif

View File

@ -21,56 +21,12 @@
*/ */
#include "rsa.h" #include "rsa.h"
#include <gmp.h>
Rsa::Rsa() void RSA::encrypt(char *msg, int size, const char* key)
{ {
m_keySet = false; assert(size <= 128);
mpz_init2(m_p, 1024);
mpz_init2(m_q, 1024);
mpz_init2(m_d, 1024);
mpz_init2(m_u, 1024);
mpz_init2(m_dp, 1024);
mpz_init2(m_dq, 1024);
mpz_init2(m_mod, 1024);
}
Rsa::~Rsa()
{
mpz_clear(m_p);
mpz_clear(m_q);
mpz_clear(m_d);
mpz_clear(m_u);
mpz_clear(m_dp);
mpz_clear(m_dq);
mpz_clear(m_mod);
}
void Rsa::setKey(const char* p, const char* q, const char* d)
{
mpz_set_str(m_p, p, 10);
mpz_set_str(m_q, q, 10);
mpz_set_str(m_d, d, 10);
mpz_t pm1,qm1;
mpz_init2(pm1,520);
mpz_init2(qm1,520);
mpz_sub_ui(pm1, m_p, 1);
mpz_sub_ui(qm1, m_q, 1);
mpz_invert(m_u, m_p, m_q);
mpz_mod(m_dp, m_d, pm1);
mpz_mod(m_dq, m_d, qm1);
mpz_mul(m_mod, m_p, m_q);
mpz_clear(pm1);
mpz_clear(qm1);
m_keySet = true;
}
void Rsa::encrypt(char* msg, int32_t size, const char* key)
{
mpz_t plain, c; mpz_t plain, c;
mpz_init2(plain, 1024); mpz_init2(plain, 1024);
mpz_init2(c, 1024); mpz_init2(c, 1024);
@ -83,12 +39,12 @@ void Rsa::encrypt(char* msg, int32_t size, const char* key)
mpz_init2(mod, 1024); mpz_init2(mod, 1024);
mpz_set_str(mod, key, 10); mpz_set_str(mod, key, 10);
mpz_import(plain, 128, 1, 1, 0, 0, msg); mpz_import(plain, size, 1, 1, 0, 0, msg);
mpz_powm(c, plain, e, mod); mpz_powm(c, plain, e, mod);
size_t count = (mpz_sizeinbase(c, 2) + 7)/8; size_t count = (mpz_sizeinbase(c, 2) + 7)/8;
memset(msg, 0, 128 - count); memset(msg, 0, size - count);
mpz_export(&msg[128 - count], NULL, 1, 1, 0, 0, c); mpz_export(&msg[size - count], NULL, 1, 1, 0, 0, c);
mpz_clear(c); mpz_clear(c);
mpz_clear(plain); mpz_clear(plain);
@ -96,43 +52,73 @@ void Rsa::encrypt(char* msg, int32_t size, const char* key)
mpz_clear(mod); mpz_clear(mod);
} }
bool Rsa::decrypt(char* msg, int32_t size) void RSA::decrypt(char *msg, int size, const char *p, const char *q, const char *d)
{ {
if(!m_keySet) assert(size <= 128);
return false;
mpz_t c,v1,v2,u2,tmp; mpz_t mp, mq, md, u, dp, dq, mod, c, v1, v2, u2, tmp;
mpz_init2(mp, 1024);
mpz_init2(mq, 1024);
mpz_init2(md, 1024);
mpz_init2(u, 1024);
mpz_init2(dp, 1024);
mpz_init2(dq, 1024);
mpz_init2(mod, 1024);
mpz_init2(c, 1024); mpz_init2(c, 1024);
mpz_init2(v1, 1024); mpz_init2(v1, 1024);
mpz_init2(v2, 1024); mpz_init2(v2, 1024);
mpz_init2(u2, 1024); mpz_init2(u2, 1024);
mpz_init2(tmp, 1024); mpz_init2(tmp, 1024);
mpz_import(c, 128, 1, 1, 0, 0, msg); mpz_set_str(mp, p, 10);
mpz_set_str(mq, q, 10);
mpz_set_str(md, d, 10);
mpz_mod(tmp, c, m_p); mpz_t pm1,qm1;
mpz_powm(v1, tmp, m_dp, m_p); mpz_init2(pm1, 520);
mpz_mod(tmp, c, m_q); mpz_init2(qm1, 520);
mpz_powm(v2, tmp, m_dq, m_q);
mpz_sub_ui(pm1, mp, 1);
mpz_sub_ui(qm1, mq, 1);
mpz_invert(u, mp, mq);
mpz_mod(dp, md, pm1);
mpz_mod(dq, md, qm1);
mpz_mul(mod, mp, mq);
mpz_import(c, size, 1, 1, 0, 0, msg);
mpz_mod(tmp, c, mp);
mpz_powm(v1, tmp, dp, mp);
mpz_mod(tmp, c, mq);
mpz_powm(v2, tmp, dq, mq);
mpz_sub(u2, v2, v1); mpz_sub(u2, v2, v1);
mpz_mul(tmp, u2, m_u); mpz_mul(tmp, u2, u);
mpz_mod(u2, tmp, m_q); mpz_mod(u2, tmp, mq);
if(mpz_cmp_si(u2, 0) < 0){ if(mpz_cmp_si(u2, 0) < 0) {
mpz_add(tmp, u2, m_q); mpz_add(tmp, u2, mq);
mpz_set(u2, tmp); mpz_set(u2, tmp);
} }
mpz_mul(tmp, u2, m_p); mpz_mul(tmp, u2, mp);
mpz_set_ui(c, 0); mpz_set_ui(c, 0);
mpz_add(c, v1, tmp); mpz_add(c, v1, tmp);
size_t count = (mpz_sizeinbase(c, 2) + 7)/8; size_t count = (mpz_sizeinbase(c, 2) + 7)/8;
memset(msg, 0, 128 - count); memset(msg, 0, size - count);
mpz_export(&msg[128 - count], NULL, 1, 1, 0, 0, c); mpz_export(&msg[size - count], NULL, 1, 1, 0, 0, c);
mpz_clear(c); mpz_clear(c);
mpz_clear(v1); mpz_clear(v1);
mpz_clear(v2); mpz_clear(v2);
mpz_clear(u2); mpz_clear(u2);
mpz_clear(tmp); mpz_clear(tmp);
return true; mpz_clear(pm1);
mpz_clear(qm1);
mpz_clear(mp);
mpz_clear(mq);
mpz_clear(md);
mpz_clear(u);
mpz_clear(dp);
mpz_clear(dq);
mpz_clear(mod);
} }

View File

@ -24,22 +24,11 @@
#define RSA_H #define RSA_H
#include <framework/global.h> #include <framework/global.h>
#include <gmp.h>
class Rsa namespace RSA
{ {
public: void encrypt(char *msg, int size, const char *key);
Rsa(); void decrypt(char *msg, int size, const char *p, const char *q, const char *d);
~Rsa();
void setKey(const char* p, const char* q, const char* d);
bool decrypt(char* msg, int32_t size);
static void encrypt(char* msg, int32_t size, const char* key);
protected:
bool m_keySet;
mpz_t m_p, m_q, m_u, m_d, m_dp, m_dq, m_mod;
}; };
#endif #endif

View File

@ -63,7 +63,6 @@ void UIManager::resize(const Size& size)
void UIManager::inputEvent(const InputEvent& event) void UIManager::inputEvent(const InputEvent& event)
{ {
m_isOnInputEvent = true;
UIWidgetList widgetList; UIWidgetList widgetList;
switch(event.type) { switch(event.type) {
case Fw::KeyTextInputEvent: case Fw::KeyTextInputEvent:
@ -155,7 +154,6 @@ void UIManager::inputEvent(const InputEvent& event)
default: default:
break; break;
}; };
m_isOnInputEvent = false;
} }
void UIManager::updatePressedWidget(const UIWidgetPtr& newPressedWidget, const Point& clickedPos) void UIManager::updatePressedWidget(const UIWidgetPtr& newPressedWidget, const Point& clickedPos)

View File

@ -62,7 +62,6 @@ public:
UIWidgetPtr getPressedWidget() { return m_pressedWidget; } UIWidgetPtr getPressedWidget() { return m_pressedWidget; }
UIWidgetPtr getRootWidget() { return m_rootWidget; } UIWidgetPtr getRootWidget() { return m_rootWidget; }
bool isOnInputEvent() { return m_isOnInputEvent; }
bool isDrawingDebugBoxes() { return m_drawDebugBoxes; } bool isDrawingDebugBoxes() { return m_drawDebugBoxes; }
protected: protected:
@ -80,7 +79,6 @@ private:
UIWidgetPtr m_hoveredWidget; UIWidgetPtr m_hoveredWidget;
UIWidgetPtr m_pressedWidget; UIWidgetPtr m_pressedWidget;
Boolean<false> m_hoverUpdateScheduled; Boolean<false> m_hoverUpdateScheduled;
bool m_isOnInputEvent;
Boolean<false> m_drawDebugBoxes; Boolean<false> m_drawDebugBoxes;
std::unordered_map<std::string, OTMLNodePtr> m_styles; std::unordered_map<std::string, OTMLNodePtr> m_styles;
}; };

View File

@ -11,7 +11,7 @@ ADD_DEFINITIONS(-DPROTOCOL=${PROTOCOL})
MESSAGE(STATUS "Protocol: " ${PROTOCOL}) MESSAGE(STATUS "Protocol: " ${PROTOCOL})
IF(CIPSOFT_RSA) IF(CIPSOFT_RSA)
ADD_DEFINITIONS(-DCIPSOFT_RSA) ADD_DEFINITIONS(-DCIPSOFT_RSA -DOSTYPE=2)
MESSAGE(STATUS "RSA: CipSoft") MESSAGE(STATUS "RSA: CipSoft")
ELSE() ELSE()
MESSAGE(STATUS "RSA: OTServ") MESSAGE(STATUS "RSA: OTServ")

View File

@ -29,6 +29,7 @@
#include "statictext.h" #include "statictext.h"
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <framework/ui/uimanager.h> #include <framework/ui/uimanager.h>
#include <framework/application.h>
#include <otclient/luascript/luavaluecasts.h> #include <otclient/luascript/luavaluecasts.h>
#include <otclient/net/protocolgame.h> #include <otclient/net/protocolgame.h>
@ -993,7 +994,7 @@ bool Game::checkBotProtection()
#ifdef BOT_PROTECTION #ifdef BOT_PROTECTION
// accepts calls comming from a stacktrace containing only C++ functions, // accepts calls comming from a stacktrace containing only C++ functions,
// if the stacktrace contains a lua function, then only accept if the engine is processing an input event // if the stacktrace contains a lua function, then only accept if the engine is processing an input event
if(g_lua.isInCppCallback() && !g_ui.isOnInputEvent()) { if(g_lua.isInCppCallback() && !g_app->isOnInputEvent()) {
logError(g_lua.traceback("caught a lua call to a bot protected game function, the call was canceled")); logError(g_lua.traceback("caught a lua call to a bot protected game function, the call was canceled"));
return false; return false;
} }

View File

@ -175,6 +175,19 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassMemberFunction<ProtocolLogin>("cancelLogin", &ProtocolLogin::cancelLogin); g_lua.bindClassMemberFunction<ProtocolLogin>("cancelLogin", &ProtocolLogin::cancelLogin);
g_lua.registerClass<ProtocolGame, Protocol>(); g_lua.registerClass<ProtocolGame, Protocol>();
g_lua.bindClassStaticFunction<ProtocolGame>("create", []{ return ProtocolGamePtr(new ProtocolGame); });
g_lua.bindClassMemberFunction<ProtocolGame>("login", &ProtocolGame::login);
g_lua.bindClassMemberFunction<ProtocolGame>("send", &ProtocolGame::send);
g_lua.bindClassMemberFunction<ProtocolGame>("sendExtendedOpcode", &ProtocolGame::sendExtendedOpcode);
g_lua.bindClassMemberFunction<ProtocolGame>("addPosition", &ProtocolGame::addPosition);
g_lua.bindClassMemberFunction<ProtocolGame>("setMapDescription", &ProtocolGame::setMapDescription);
g_lua.bindClassMemberFunction<ProtocolGame>("setFloorDescription", &ProtocolGame::setFloorDescription);
g_lua.bindClassMemberFunction<ProtocolGame>("setTileDescription", &ProtocolGame::setTileDescription);
g_lua.bindClassMemberFunction<ProtocolGame>("getOutfit", &ProtocolGame::getOutfit);
g_lua.bindClassMemberFunction<ProtocolGame>("getThing", &ProtocolGame::getThing);
g_lua.bindClassMemberFunction<ProtocolGame>("getCreature", &ProtocolGame::getCreature);
g_lua.bindClassMemberFunction<ProtocolGame>("getItem", &ProtocolGame::getItem);
g_lua.bindClassMemberFunction<ProtocolGame>("getPosition", &ProtocolGame::getPosition);
g_lua.registerClass<Container>(); g_lua.registerClass<Container>();
g_lua.bindClassStaticFunction<Container>("create", []{ return ContainerPtr(new Container); }); g_lua.bindClassStaticFunction<Container>("create", []{ return ContainerPtr(new Container); });
@ -256,7 +269,6 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassMemberFunction<Item>("getId", &Item::getId); g_lua.bindClassMemberFunction<Item>("getId", &Item::getId);
g_lua.bindClassMemberFunction<Item>("isStackable", &Item::isStackable); g_lua.bindClassMemberFunction<Item>("isStackable", &Item::isStackable);
g_lua.registerClass<Effect, Thing>(); g_lua.registerClass<Effect, Thing>();
g_lua.registerClass<Missile, Thing>(); g_lua.registerClass<Missile, Thing>();
g_lua.registerClass<StaticText, Thing>(); g_lua.registerClass<StaticText, Thing>();

View File

@ -55,15 +55,17 @@ namespace Proto {
OsLinux = 1, OsLinux = 1,
OsWindows = 2, OsWindows = 2,
OsFlash = 3, OsFlash = 3,
OsMac = 4 OsOtclientLinux = 10,
OsOtclientWindows = 11,
OsOtclientMac = 12,
}; };
#ifdef OSTYPE #ifdef OSTYPE
constexpr int ClientOs = OSTYPE; constexpr int ClientOs = OSTYPE;
#elif defined WIN32 #elif defined WIN32
constexpr int ClientOs = OsWindows; constexpr int ClientOs = OsOtclientWindows;
#else #else
constexpr int ClientOs = OsLinux; constexpr int ClientOs = OsOtclientLinux;
#endif #endif
#if PROTOCOL>=860 #if PROTOCOL>=860
@ -107,10 +109,9 @@ namespace Proto {
GameServerFirstGameOpcode = 50, GameServerFirstGameOpcode = 50,
// NOTE: add any custom opcodes in this range // NOTE: add any custom opcodes in this range
// 50 - 97 // 51 - 99
// otclient ONLY // otclient ONLY
GameServerExtendedP2POpcode = 98,
GameServerExtendedOpcode = 99, GameServerExtendedOpcode = 99,
// original tibia ONLY // original tibia ONLY
@ -203,10 +204,9 @@ namespace Proto {
ClientFirstGameOpcode = 50, ClientFirstGameOpcode = 50,
// NOTE: add any custom opcodes in this range // NOTE: add any custom opcodes in this range
// 50 - 97 // 50 - 98
// otclient ONLY // otclient ONLY
ClientExtendedP2POpcode = 98,
ClientExtendedOpcode = 99, ClientExtendedOpcode = 99,
// original tibia ONLY // original tibia ONLY

View File

@ -54,7 +54,7 @@ void ProtocolGame::onConnect()
recv(); recv();
} }
void ProtocolGame::onRecv(InputMessage& inputMessage) void ProtocolGame::onRecv(const InputMessagePtr& inputMessage)
{ {
parseMessage(inputMessage); parseMessage(inputMessage);
recv(); recv();

View File

@ -32,11 +32,18 @@ class ProtocolGame : public Protocol
{ {
public: public:
void login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName); void login(const std::string& accountName, const std::string& accountPassword, const std::string& host, uint16 port, const std::string& characterName);
void send(const OutputMessagePtr& outputMessage);
void sendExtendedOpcode(uint8 opcode, const std::string& buffer);
protected:
void onConnect(); void onConnect();
void onRecv(InputMessage& inputMessage); void onRecv(const InputMessagePtr& inputMessage);
void onError(const boost::system::error_code& error); void onError(const boost::system::error_code& error);
friend class Game;
protected:
void sendLoginPacket(uint challangeTimestamp, uint8 challangeRandom);
void sendLogout(); void sendLogout();
void sendPing(); void sendPing();
void sendPingBack(); void sendPingBack();
@ -105,115 +112,105 @@ public:
void sendRequestQuestLine(int questId); void sendRequestQuestLine(int questId);
void sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation); void sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation);
void sendRequestItemInfo(int itemId, int index); void sendRequestItemInfo(int itemId, int index);
/*
void sendMarketLeave(); public:
void sendMarketBrowse(); void addPosition(const OutputMessagePtr& msg, const Position& position);
void sendMarketCreate();
void sendMarketCancel();
void sendMarketAccept();
*/
void sendExtendedOpcode(uint8 opcode, const std::string& buffer);
private: private:
void sendLoginPacket(uint challangeTimestamp, uint8 challangeRandom); void parseMessage(const InputMessagePtr& msg);
void parseInitGame(const InputMessagePtr& msg);
void parseGMActions(const InputMessagePtr& msg);
void parseLoginError(const InputMessagePtr& msg);
void parseLoginAdvice(const InputMessagePtr& msg);
void parseLoginWait(const InputMessagePtr& msg);
void parsePing(const InputMessagePtr& msg);
void parsePingBack(const InputMessagePtr& msg);
void parseChallange(const InputMessagePtr& msg);
void parseDeath(const InputMessagePtr& msg);
void parseMapDescription(const InputMessagePtr& msg);
void parseMapMoveNorth(const InputMessagePtr& msg);
void parseMapMoveEast(const InputMessagePtr& msg);
void parseMapMoveSouth(const InputMessagePtr& msg);
void parseMapMoveWest(const InputMessagePtr& msg);
void parseUpdateTile(const InputMessagePtr& msg);
void parseTileAddThing(const InputMessagePtr& msg);
void parseTileTransformThing(const InputMessagePtr& msg);
void parseTileRemoveThing(const InputMessagePtr& msg);
void parseCreatureMove(const InputMessagePtr& msg);
void parseOpenContainer(const InputMessagePtr& msg);
void parseCloseContainer(const InputMessagePtr& msg);
void parseContainerAddItem(const InputMessagePtr& msg);
void parseContainerUpdateItem(const InputMessagePtr& msg);
void parseContainerRemoveItem(const InputMessagePtr& msg);
void parseAddInventoryItem(const InputMessagePtr& msg);
void parseRemoveInventoryItem(const InputMessagePtr& msg);
void parseOpenNpcTrade(const InputMessagePtr& msg);
void parsePlayerGoods(const InputMessagePtr& msg);
void parseCloseNpcTrade(const InputMessagePtr&);
void parseWorldLight(const InputMessagePtr& msg);
void parseMagicEffect(const InputMessagePtr& msg);
void parseAnimatedText(const InputMessagePtr& msg);
void parseDistanceMissile(const InputMessagePtr& msg);
void parseCreatureMark(const InputMessagePtr& msg);
void parseTrappers(const InputMessagePtr& msg);
void parseCreatureHealth(const InputMessagePtr& msg);
void parseCreatureLight(const InputMessagePtr& msg);
void parseCreatureOutfit(const InputMessagePtr& msg);
void parseCreatureSpeed(const InputMessagePtr& msg);
void parseCreatureSkulls(const InputMessagePtr& msg);
void parseCreatureShields(const InputMessagePtr& msg);
void parseCreatureUnpass(const InputMessagePtr& msg);
void parseEditText(const InputMessagePtr& msg);
void parseEditList(const InputMessagePtr& msg);
void parsePlayerInfo(const InputMessagePtr& msg);
void parsePlayerStats(const InputMessagePtr& msg);
void parsePlayerSkills(const InputMessagePtr& msg);
void parsePlayerState(const InputMessagePtr& msg);
void parsePlayerCancelAttack(const InputMessagePtr& msg);
void parseSpellDelay(const InputMessagePtr& msg);
void parseSpellGroupDelay(const InputMessagePtr& msg);
void parseMultiUseDelay(const InputMessagePtr& msg);
void parseCreatureSpeak(const InputMessagePtr& msg);
void parseChannelList(const InputMessagePtr& msg);
void parseOpenChannel(const InputMessagePtr& msg);
void parseOpenPrivateChannel(const InputMessagePtr& msg);
void parseOpenOwnPrivateChannel(const InputMessagePtr& msg);
void parseCloseChannel(const InputMessagePtr& msg);
void parseRuleViolationChannel(const InputMessagePtr& msg);
void parseRuleViolationRemove(const InputMessagePtr& msg);
void parseRuleViolationCancel(const InputMessagePtr& msg);
void parseRuleViolationLock(const InputMessagePtr& msg);
void parseOwnTrade(const InputMessagePtr& msg);
void parseCounterTrade(const InputMessagePtr& msg);
void parseCloseTrade(const InputMessagePtr&);
void parseTextMessage(const InputMessagePtr& msg);
void parseCancelWalk(const InputMessagePtr& msg);
void parseWalkWait(const InputMessagePtr& msg);
void parseFloorChangeUp(const InputMessagePtr& msg);
void parseFloorChangeDown(const InputMessagePtr& msg);
void parseOpenOutfitWindow(const InputMessagePtr& msg);
void parseVipAdd(const InputMessagePtr& msg);
void parseVipLogin(const InputMessagePtr& msg);
void parseVipLogout(const InputMessagePtr& msg);
void parseTutorialHint(const InputMessagePtr& msg);
void parseAutomapFlag(const InputMessagePtr& msg);
void parseQuestLog(const InputMessagePtr& msg);
void parseQuestLine(const InputMessagePtr& msg);
void parseChannelEvent(const InputMessagePtr& msg);
void parseItemInfo(const InputMessagePtr& msg);
void parsePlayerInventory(const InputMessagePtr& msg);
void parseExtendedOpcode(const InputMessagePtr& msg);
// Parse Messages public:
void parseMessage(InputMessage& msg); void setMapDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height);
int setFloorDescription(const InputMessagePtr& msg, int x, int y, int z, int width, int height, int offset, int skip);
void setTileDescription(const InputMessagePtr& msg, Position position);
void parseInitGame(InputMessage& msg); Outfit getOutfit(const InputMessagePtr& msg);
void parseGMActions(InputMessage& msg); ThingPtr getThing(const InputMessagePtr& msg);
void parseLoginError(InputMessage& msg); CreaturePtr getCreature(const InputMessagePtr& msg, int type = 0);
void parseLoginAdvice(InputMessage& msg); ItemPtr getItem(const InputMessagePtr& msg, int id = 0);
void parseLoginWait(InputMessage& msg); Position getPosition(const InputMessagePtr& msg);
void parsePing(InputMessage& msg);
void parsePingBack(InputMessage& msg);
void parseChallange(InputMessage& msg);
void parseDeath(InputMessage& msg);
void parseMapDescription(InputMessage& msg);
void parseMapMoveNorth(InputMessage& msg);
void parseMapMoveEast(InputMessage& msg);
void parseMapMoveSouth(InputMessage& msg);
void parseMapMoveWest(InputMessage& msg);
void parseUpdateTile(InputMessage& msg);
void parseTileAddThing(InputMessage& msg);
void parseTileTransformThing(InputMessage& msg);
void parseTileRemoveThing(InputMessage& msg);
void parseCreatureMove(InputMessage& msg);
void parseOpenContainer(InputMessage& msg);
void parseCloseContainer(InputMessage& msg);
void parseContainerAddItem(InputMessage& msg);
void parseContainerUpdateItem(InputMessage& msg);
void parseContainerRemoveItem(InputMessage& msg);
void parseAddInventoryItem(InputMessage& msg);
void parseRemoveInventoryItem(InputMessage& msg);
void parseOpenNpcTrade(InputMessage& msg);
void parsePlayerGoods(InputMessage& msg);
void parseCloseNpcTrade(InputMessage&);
void parseWorldLight(InputMessage& msg);
void parseMagicEffect(InputMessage& msg);
void parseAnimatedText(InputMessage& msg);
void parseDistanceMissile(InputMessage& msg);
void parseCreatureMark(InputMessage& msg);
void parseTrappers(InputMessage& msg);
void parseCreatureHealth(InputMessage& msg);
void parseCreatureLight(InputMessage& msg);
void parseCreatureOutfit(InputMessage& msg);
void parseCreatureSpeed(InputMessage& msg);
void parseCreatureSkulls(InputMessage& msg);
void parseCreatureShields(InputMessage& msg);
void parseCreatureUnpass(InputMessage& msg);
void parseEditText(InputMessage& msg);
void parseEditList(InputMessage& msg);
void parsePlayerInfo(InputMessage& msg);
void parsePlayerStats(InputMessage& msg);
void parsePlayerSkills(InputMessage& msg);
void parsePlayerState(InputMessage& msg);
void parsePlayerCancelAttack(InputMessage& msg);
void parseSpellDelay(InputMessage& msg);
void parseSpellGroupDelay(InputMessage& msg);
void parseMultiUseDelay(InputMessage& msg);
void parseCreatureSpeak(InputMessage& msg);
void parseChannelList(InputMessage& msg);
void parseOpenChannel(InputMessage& msg);
void parseOpenPrivateChannel(InputMessage& msg);
void parseOpenOwnPrivateChannel(InputMessage& msg);
void parseCloseChannel(InputMessage& msg);
void parseRuleViolationChannel(InputMessage& msg);
void parseRuleViolationRemove(InputMessage& msg);
void parseRuleViolationCancel(InputMessage& msg);
void parseRuleViolationLock(InputMessage& msg);
void parseOwnTrade(InputMessage& msg);
void parseCounterTrade(InputMessage& msg);
void parseCloseTrade(InputMessage&);
void parseTextMessage(InputMessage& msg);
void parseCancelWalk(InputMessage& msg);
void parseWalkWait(InputMessage& msg);
void parseFloorChangeUp(InputMessage& msg);
void parseFloorChangeDown(InputMessage& msg);
void parseOpenOutfitWindow(InputMessage& msg);
void parseVipAdd(InputMessage& msg);
void parseVipLogin(InputMessage& msg);
void parseVipLogout(InputMessage& msg);
void parseTutorialHint(InputMessage& msg);
void parseAutomapFlag(InputMessage& msg);
void parseQuestLog(InputMessage& msg);
void parseQuestLine(InputMessage& msg);
void parseChannelEvent(InputMessage& msg);
void parseItemInfo(InputMessage& msg);
void parsePlayerInventory(InputMessage& msg);
void parseExtendedOpcode(InputMessage& msg);
void setMapDescription(InputMessage& msg, int x, int y, int z, int width, int height);
void setFloorDescription(InputMessage& msg, int x, int y, int z, int width, int height, int offset, int* skipTiles);
void setTileDescription(InputMessage& msg, Position position);
Outfit internalGetOutfit(InputMessage& msg);
CreaturePtr internalGetCreature(InputMessage& msg, int type = 0);
ThingPtr internalGetThing(InputMessage& msg);
ItemPtr internalGetItem(InputMessage& msg, int id = 0);
void addPosition(OutputMessage& msg, const Position& position);
Position parsePosition(InputMessage& msg);
private: private:
Boolean<false> m_gameInitialized; Boolean<false> m_gameInitialized;

File diff suppressed because it is too large Load Diff

View File

@ -21,68 +21,72 @@
*/ */
#include "protocolgame.h" #include "protocolgame.h"
#include <framework/net/rsa.h> #include <otclient/core/game.h>
void ProtocolGame::send(const OutputMessagePtr& outputMessage)
{
// avoid usage of automated sends (bot modules)
if(!g_game.checkBotProtection())
return;
Protocol::send(outputMessage);
}
void ProtocolGame::sendExtendedOpcode(uint8 opcode, const std::string& buffer)
{
OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientExtendedOpcode);
msg->addU8(opcode);
msg->addString(buffer);
send(msg);
}
/*
ClientEquipObject
ClientRefreshContainer
ClientMount
ClientRuleViolationReport
ClientGetItemInfo
ClientMarketLeave
ClientMarketBrowse
ClientMarketCreate
ClientMarketCancel
ClientMarketAccept
ClientExtendedOpcode = 254 // otclient only
*/
void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRandom) void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRandom)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientEnterGame); msg->addU8(Proto::ClientEnterGame);
msg.addU16(Proto::ClientOs); msg->addU16(Proto::ClientOs);
msg.addU16(Proto::ClientVersion); msg->addU16(Proto::ClientVersion);
int paddingBytes = 128; int paddingBytes = 128;
msg.addU8(0); // first RSA byte must be 0 msg->addU8(0); // first RSA byte must be 0
paddingBytes -= 1; paddingBytes -= 1;
// xtea key // xtea key
generateXteaKey(); generateXteaKey();
msg.addU32(m_xteaKey[0]); msg->addU32(m_xteaKey[0]);
msg.addU32(m_xteaKey[1]); msg->addU32(m_xteaKey[1]);
msg.addU32(m_xteaKey[2]); msg->addU32(m_xteaKey[2]);
msg.addU32(m_xteaKey[3]); msg->addU32(m_xteaKey[3]);
msg.addU8(0); // is gm set? msg->addU8(0); // is gm set?
paddingBytes -= 17; paddingBytes -= 17;
#if PROTOCOL>=854 #if PROTOCOL>=854
enableChecksum(); enableChecksum();
msg.addString(m_accountName); msg->addString(m_accountName);
paddingBytes -= 2 + m_accountName.length(); paddingBytes -= 2 + m_accountName.length();
msg.addString(m_characterName); msg->addString(m_characterName);
paddingBytes -= 2 + m_characterName.length(); paddingBytes -= 2 + m_characterName.length();
msg.addString(m_accountPassword); msg->addString(m_accountPassword);
paddingBytes -= 2 + m_accountPassword.length(); paddingBytes -= 2 + m_accountPassword.length();
msg.addU32(challangeTimestamp); msg->addU32(challangeTimestamp);
msg.addU8(challangeRandom); msg->addU8(challangeRandom);
paddingBytes -= 5; paddingBytes -= 5;
#else // PROTOCOL>=810 #else // PROTOCOL>=810
msg.addU32(Fw::fromstring<uint32>(m_accountName)); msg->addU32(Fw::fromstring<uint32>(m_accountName));
msg.addString(m_characterName); msg->addString(m_characterName);
msg.addString(m_accountPassword); msg->addString(m_accountPassword);
paddingBytes -= 8 + m_characterName.length() + m_accountPassword.length(); paddingBytes -= 8 + m_characterName.length() + m_accountPassword.length();
#endif #endif
// complete the 128 bytes for rsa encryption with zeros // complete the 128 bytes for rsa encryption with zeros
msg.addPaddingBytes(paddingBytes); msg->addPaddingBytes(paddingBytes);
// encrypt with RSA // encrypt with RSA
Rsa::encrypt((char*)msg.getWriteBuffer() - 128, 128, Proto::RSA); msg->encryptRSA(128, Proto::RSA);
send(msg); send(msg);
@ -91,30 +95,30 @@ void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRando
void ProtocolGame::sendLogout() void ProtocolGame::sendLogout()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientLeaveGame); msg->addU8(Proto::ClientLeaveGame);
send(msg); send(msg);
} }
void ProtocolGame::sendPing() void ProtocolGame::sendPing()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientPing); msg->addU8(Proto::ClientPing);
send(msg); send(msg);
} }
void ProtocolGame::sendPingBack() void ProtocolGame::sendPingBack()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientPingBack); msg->addU8(Proto::ClientPingBack);
send(msg); send(msg);
} }
void ProtocolGame::sendAutoWalk(const std::vector<Otc::Direction>& path) void ProtocolGame::sendAutoWalk(const std::vector<Otc::Direction>& path)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientAutoWalk); msg->addU8(Proto::ClientAutoWalk);
msg.addU8(path.size()); msg->addU8(path.size());
for(Otc::Direction dir : path) { for(Otc::Direction dir : path) {
uint8 byte; uint8 byte;
switch(dir) { switch(dir) {
@ -146,283 +150,283 @@ void ProtocolGame::sendAutoWalk(const std::vector<Otc::Direction>& path)
byte = 0; byte = 0;
break; break;
} }
msg.addU8(byte); msg->addU8(byte);
} }
send(msg); send(msg);
} }
void ProtocolGame::sendWalkNorth() void ProtocolGame::sendWalkNorth()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientWalkNorth); msg->addU8(Proto::ClientWalkNorth);
send(msg); send(msg);
} }
void ProtocolGame::sendWalkEast() void ProtocolGame::sendWalkEast()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientWalkEast); msg->addU8(Proto::ClientWalkEast);
send(msg); send(msg);
} }
void ProtocolGame::sendWalkSouth() void ProtocolGame::sendWalkSouth()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientWalkSouth); msg->addU8(Proto::ClientWalkSouth);
send(msg); send(msg);
} }
void ProtocolGame::sendWalkWest() void ProtocolGame::sendWalkWest()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientWalkWest); msg->addU8(Proto::ClientWalkWest);
send(msg); send(msg);
} }
void ProtocolGame::sendStop() void ProtocolGame::sendStop()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientStop); msg->addU8(Proto::ClientStop);
send(msg); send(msg);
} }
void ProtocolGame::sendWalkNorthEast() void ProtocolGame::sendWalkNorthEast()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientWalkNorthEast); msg->addU8(Proto::ClientWalkNorthEast);
send(msg); send(msg);
} }
void ProtocolGame::sendWalkSouthEast() void ProtocolGame::sendWalkSouthEast()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientWalkSouthEast); msg->addU8(Proto::ClientWalkSouthEast);
send(msg); send(msg);
} }
void ProtocolGame::sendWalkSouthWest() void ProtocolGame::sendWalkSouthWest()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientWalkSouthWest); msg->addU8(Proto::ClientWalkSouthWest);
send(msg); send(msg);
} }
void ProtocolGame::sendWalkNorthWest() void ProtocolGame::sendWalkNorthWest()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientWalkNorthWest); msg->addU8(Proto::ClientWalkNorthWest);
send(msg); send(msg);
} }
void ProtocolGame::sendTurnNorth() void ProtocolGame::sendTurnNorth()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientTurnNorth); msg->addU8(Proto::ClientTurnNorth);
send(msg); send(msg);
} }
void ProtocolGame::sendTurnEast() void ProtocolGame::sendTurnEast()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientTurnEast); msg->addU8(Proto::ClientTurnEast);
send(msg); send(msg);
} }
void ProtocolGame::sendTurnSouth() void ProtocolGame::sendTurnSouth()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientTurnSouth); msg->addU8(Proto::ClientTurnSouth);
send(msg); send(msg);
} }
void ProtocolGame::sendTurnWest() void ProtocolGame::sendTurnWest()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientTurnWest); msg->addU8(Proto::ClientTurnWest);
send(msg); send(msg);
} }
void ProtocolGame::sendEquipItem(int itemId, int countOrSubType) void ProtocolGame::sendEquipItem(int itemId, int countOrSubType)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientEquipItem); msg->addU8(Proto::ClientEquipItem);
msg.addU16(itemId); msg->addU16(itemId);
msg.addU8(countOrSubType); msg->addU8(countOrSubType);
send(msg); send(msg);
} }
void ProtocolGame::sendMove(const Position& fromPos, int thingId, int stackpos, const Position& toPos, int count) void ProtocolGame::sendMove(const Position& fromPos, int thingId, int stackpos, const Position& toPos, int count)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientMove); msg->addU8(Proto::ClientMove);
addPosition(msg, fromPos); addPosition(msg, fromPos);
msg.addU16(thingId); msg->addU16(thingId);
msg.addU8(stackpos); msg->addU8(stackpos);
addPosition(msg, toPos); addPosition(msg, toPos);
msg.addU8(count); msg->addU8(count);
send(msg); send(msg);
} }
void ProtocolGame::sendInspectNpcTrade(int itemId, int count) void ProtocolGame::sendInspectNpcTrade(int itemId, int count)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientInspectNpcTrade); msg->addU8(Proto::ClientInspectNpcTrade);
msg.addU16(itemId); msg->addU16(itemId);
msg.addU8(count); msg->addU8(count);
send(msg); send(msg);
} }
void ProtocolGame::sendBuyItem(int itemId, int subType, int amount, bool ignoreCapacity, bool buyWithBackpack) void ProtocolGame::sendBuyItem(int itemId, int subType, int amount, bool ignoreCapacity, bool buyWithBackpack)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientBuyItem); msg->addU8(Proto::ClientBuyItem);
msg.addU16(itemId); msg->addU16(itemId);
msg.addU8(subType); msg->addU8(subType);
msg.addU8(amount); msg->addU8(amount);
msg.addU8(ignoreCapacity ? 0x01 : 0x00); msg->addU8(ignoreCapacity ? 0x01 : 0x00);
msg.addU8(buyWithBackpack ? 0x01 : 0x00); msg->addU8(buyWithBackpack ? 0x01 : 0x00);
send(msg); send(msg);
} }
void ProtocolGame::sendSellItem(int itemId, int subType, int amount, bool ignoreEquipped) void ProtocolGame::sendSellItem(int itemId, int subType, int amount, bool ignoreEquipped)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientSellItem); msg->addU8(Proto::ClientSellItem);
msg.addU16(itemId); msg->addU16(itemId);
msg.addU8(subType); msg->addU8(subType);
msg.addU8(amount); msg->addU8(amount);
msg.addU8(ignoreEquipped ? 0x01 : 0x00); msg->addU8(ignoreEquipped ? 0x01 : 0x00);
send(msg); send(msg);
} }
void ProtocolGame::sendCloseNpcTrade() void ProtocolGame::sendCloseNpcTrade()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientCloseNpcTrade); msg->addU8(Proto::ClientCloseNpcTrade);
send(msg); send(msg);
} }
void ProtocolGame::sendRequestTrade(const Position& pos, int thingId, int stackpos, uint creatureId) void ProtocolGame::sendRequestTrade(const Position& pos, int thingId, int stackpos, uint creatureId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRequestTrade); msg->addU8(Proto::ClientRequestTrade);
addPosition(msg, pos); addPosition(msg, pos);
msg.addU16(thingId); msg->addU16(thingId);
msg.addU8(stackpos); msg->addU8(stackpos);
msg.addU32(creatureId); msg->addU32(creatureId);
send(msg); send(msg);
} }
void ProtocolGame::sendInspectTrade(bool counterOffer, int index) void ProtocolGame::sendInspectTrade(bool counterOffer, int index)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientInspectTrade); msg->addU8(Proto::ClientInspectTrade);
msg.addU8(counterOffer ? 0x01 : 0x00); msg->addU8(counterOffer ? 0x01 : 0x00);
msg.addU8(index); msg->addU8(index);
send(msg); send(msg);
} }
void ProtocolGame::sendAcceptTrade() void ProtocolGame::sendAcceptTrade()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientAcceptTrade); msg->addU8(Proto::ClientAcceptTrade);
send(msg); send(msg);
} }
void ProtocolGame::sendRejectTrade() void ProtocolGame::sendRejectTrade()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRejectTrade); msg->addU8(Proto::ClientRejectTrade);
send(msg); send(msg);
} }
void ProtocolGame::sendUseItem(const Position& position, int itemId, int stackpos, int index) void ProtocolGame::sendUseItem(const Position& position, int itemId, int stackpos, int index)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientUseItem); msg->addU8(Proto::ClientUseItem);
addPosition(msg, position); addPosition(msg, position);
msg.addU16(itemId); msg->addU16(itemId);
msg.addU8(stackpos); msg->addU8(stackpos);
msg.addU8(index); msg->addU8(index);
send(msg); send(msg);
} }
void ProtocolGame::sendUseItemWith(const Position& fromPos, int itemId, int fromStackpos, const Position& toPos, int toThingId, int toStackpos) void ProtocolGame::sendUseItemWith(const Position& fromPos, int itemId, int fromStackpos, const Position& toPos, int toThingId, int toStackpos)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientUseItemWith); msg->addU8(Proto::ClientUseItemWith);
addPosition(msg, fromPos); addPosition(msg, fromPos);
msg.addU16(itemId); msg->addU16(itemId);
msg.addU8(fromStackpos); msg->addU8(fromStackpos);
addPosition(msg, toPos); addPosition(msg, toPos);
msg.addU16(toThingId); msg->addU16(toThingId);
msg.addU8(toStackpos); msg->addU8(toStackpos);
send(msg); send(msg);
} }
void ProtocolGame::sendUseOnCreature(const Position& pos, int thingId, int stackpos, uint creatureId) void ProtocolGame::sendUseOnCreature(const Position& pos, int thingId, int stackpos, uint creatureId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientUseOnCreature); msg->addU8(Proto::ClientUseOnCreature);
addPosition(msg, pos); addPosition(msg, pos);
msg.addU16(thingId); msg->addU16(thingId);
msg.addU8(stackpos); msg->addU8(stackpos);
msg.addU32(creatureId); msg->addU32(creatureId);
send(msg); send(msg);
} }
void ProtocolGame::sendRotateItem(const Position& pos, int thingId, int stackpos) void ProtocolGame::sendRotateItem(const Position& pos, int thingId, int stackpos)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRotateItem); msg->addU8(Proto::ClientRotateItem);
addPosition(msg, pos); addPosition(msg, pos);
msg.addU16(thingId); msg->addU16(thingId);
msg.addU8(stackpos); msg->addU8(stackpos);
send(msg); send(msg);
} }
void ProtocolGame::sendCloseContainer(int containerId) void ProtocolGame::sendCloseContainer(int containerId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientCloseContainer); msg->addU8(Proto::ClientCloseContainer);
msg.addU8(containerId); msg->addU8(containerId);
send(msg); send(msg);
} }
void ProtocolGame::sendUpContainer(int containerId) void ProtocolGame::sendUpContainer(int containerId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientUpContainer); msg->addU8(Proto::ClientUpContainer);
msg.addU8(containerId); msg->addU8(containerId);
send(msg); send(msg);
} }
void ProtocolGame::sendEditText(uint id, const std::string& text) void ProtocolGame::sendEditText(uint id, const std::string& text)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientEditText); msg->addU8(Proto::ClientEditText);
msg.addU32(id); msg->addU32(id);
msg.addString(text); msg->addString(text);
send(msg); send(msg);
} }
void ProtocolGame::sendEditList(uint id, int doorId, const std::string& text) void ProtocolGame::sendEditList(uint id, int doorId, const std::string& text)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientEditList); msg->addU8(Proto::ClientEditList);
msg.addU8(doorId); msg->addU8(doorId);
msg.addU32(id); msg->addU32(id);
msg.addString(text); msg->addString(text);
send(msg); send(msg);
} }
void ProtocolGame::sendLook(const Position& position, int thingId, int stackpos) void ProtocolGame::sendLook(const Position& position, int thingId, int stackpos)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientLook); msg->addU8(Proto::ClientLook);
addPosition(msg, position); addPosition(msg, position);
msg.addU16(thingId); msg->addU16(thingId);
msg.addU8(stackpos); msg->addU8(stackpos);
send(msg); send(msg);
} }
@ -433,304 +437,295 @@ void ProtocolGame::sendTalk(Otc::SpeakType speakType, int channelId, const std::
int serverSpeakType = Proto::translateSpeakTypeToServer(speakType); int serverSpeakType = Proto::translateSpeakTypeToServer(speakType);
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientTalk); msg->addU8(Proto::ClientTalk);
msg.addU8(serverSpeakType); msg->addU8(serverSpeakType);
switch(serverSpeakType) { switch(serverSpeakType) {
case Proto::ServerSpeakPrivateFrom: case Proto::ServerSpeakPrivateFrom:
case Proto::ServerSpeakPrivateRedFrom: case Proto::ServerSpeakPrivateRedFrom:
msg.addString(receiver); msg->addString(receiver);
break; break;
case Proto::ServerSpeakChannelYellow: case Proto::ServerSpeakChannelYellow:
case Proto::ServerSpeakChannelRed: case Proto::ServerSpeakChannelRed:
msg.addU16(channelId); msg->addU16(channelId);
break; break;
} }
msg.addString(message); msg->addString(message);
send(msg); send(msg);
} }
void ProtocolGame::sendRequestChannels() void ProtocolGame::sendRequestChannels()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRequestChannels); msg->addU8(Proto::ClientRequestChannels);
send(msg); send(msg);
} }
void ProtocolGame::sendJoinChannel(int channelId) void ProtocolGame::sendJoinChannel(int channelId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientJoinChannel); msg->addU8(Proto::ClientJoinChannel);
msg.addU16(channelId); msg->addU16(channelId);
send(msg); send(msg);
} }
void ProtocolGame::sendLeaveChannel(int channelId) void ProtocolGame::sendLeaveChannel(int channelId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientLeaveChannel); msg->addU8(Proto::ClientLeaveChannel);
msg.addU16(channelId); msg->addU16(channelId);
send(msg); send(msg);
} }
void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver) void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientOpenPrivateChannel); msg->addU8(Proto::ClientOpenPrivateChannel);
msg.addString(receiver); msg->addString(receiver);
send(msg); send(msg);
} }
void ProtocolGame::sendCloseNpcChannel() void ProtocolGame::sendCloseNpcChannel()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientCloseNpcChannel); msg->addU8(Proto::ClientCloseNpcChannel);
send(msg); send(msg);
} }
void ProtocolGame::sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeFight) void ProtocolGame::sendChangeFightModes(Otc::FightModes fightMode, Otc::ChaseModes chaseMode, bool safeFight)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientChangeFightModes); msg->addU8(Proto::ClientChangeFightModes);
msg.addU8(fightMode); msg->addU8(fightMode);
msg.addU8(chaseMode); msg->addU8(chaseMode);
msg.addU8(safeFight ? 0x01: 0x00); msg->addU8(safeFight ? 0x01: 0x00);
send(msg); send(msg);
} }
void ProtocolGame::sendAttack(uint creatureId) void ProtocolGame::sendAttack(uint creatureId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientAttack); msg->addU8(Proto::ClientAttack);
msg.addU32(creatureId); msg->addU32(creatureId);
msg.addU32(0); msg->addU32(0);
msg.addU32(0); msg->addU32(0);
send(msg); send(msg);
} }
void ProtocolGame::sendFollow(uint creatureId) void ProtocolGame::sendFollow(uint creatureId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientFollow); msg->addU8(Proto::ClientFollow);
msg.addU32(creatureId); msg->addU32(creatureId);
send(msg); send(msg);
} }
void ProtocolGame::sendInviteToParty(uint creatureId) void ProtocolGame::sendInviteToParty(uint creatureId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientInviteToParty); msg->addU8(Proto::ClientInviteToParty);
msg.addU32(creatureId); msg->addU32(creatureId);
send(msg); send(msg);
} }
void ProtocolGame::sendJoinParty(uint creatureId) void ProtocolGame::sendJoinParty(uint creatureId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientJoinParty); msg->addU8(Proto::ClientJoinParty);
msg.addU32(creatureId); msg->addU32(creatureId);
send(msg); send(msg);
} }
void ProtocolGame::sendRevokeInvitation(uint creatureId) void ProtocolGame::sendRevokeInvitation(uint creatureId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRevokeInvitation); msg->addU8(Proto::ClientRevokeInvitation);
msg.addU32(creatureId); msg->addU32(creatureId);
send(msg); send(msg);
} }
void ProtocolGame::sendPassLeadership(uint creatureId) void ProtocolGame::sendPassLeadership(uint creatureId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientPassLeadership); msg->addU8(Proto::ClientPassLeadership);
msg.addU32(creatureId); msg->addU32(creatureId);
send(msg); send(msg);
} }
void ProtocolGame::sendLeaveParty() void ProtocolGame::sendLeaveParty()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientLeaveParty); msg->addU8(Proto::ClientLeaveParty);
send(msg); send(msg);
} }
void ProtocolGame::sendShareExperience(bool active, int unknown) void ProtocolGame::sendShareExperience(bool active, int unknown)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientShareExperience); msg->addU8(Proto::ClientShareExperience);
msg.addU8(active ? 0x01 : 0x00); msg->addU8(active ? 0x01 : 0x00);
#if PROTOCOL<910 #if PROTOCOL<910
msg.addU8(unknown); msg->addU8(unknown);
#endif #endif
send(msg); send(msg);
} }
void ProtocolGame::sendOpenOwnChannel() void ProtocolGame::sendOpenOwnChannel()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientOpenOwnChannel); msg->addU8(Proto::ClientOpenOwnChannel);
send(msg); send(msg);
} }
void ProtocolGame::sendInviteToOwnChannel(const std::string& name) void ProtocolGame::sendInviteToOwnChannel(const std::string& name)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientInviteToOwnChannel); msg->addU8(Proto::ClientInviteToOwnChannel);
msg.addString(name); msg->addString(name);
send(msg); send(msg);
} }
void ProtocolGame::sendExcludeFromOwnChannel(const std::string& name) void ProtocolGame::sendExcludeFromOwnChannel(const std::string& name)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientExcludeFromOwnChannel); msg->addU8(Proto::ClientExcludeFromOwnChannel);
msg.addString(name); msg->addString(name);
send(msg); send(msg);
} }
void ProtocolGame::sendCancelAttackAndFollow() void ProtocolGame::sendCancelAttackAndFollow()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientCancelAttackAndFollow); msg->addU8(Proto::ClientCancelAttackAndFollow);
send(msg); send(msg);
} }
void ProtocolGame::sendRefreshContainer() void ProtocolGame::sendRefreshContainer()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRefreshContainer); msg->addU8(Proto::ClientRefreshContainer);
send(msg); send(msg);
} }
void ProtocolGame::sendRequestOutfit() void ProtocolGame::sendRequestOutfit()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRequestOutfit); msg->addU8(Proto::ClientRequestOutfit);
send(msg); send(msg);
} }
void ProtocolGame::sendChangeOutfit(const Outfit& outfit) void ProtocolGame::sendChangeOutfit(const Outfit& outfit)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientChangeOutfit); msg->addU8(Proto::ClientChangeOutfit);
msg.addU16(outfit.getId()); msg->addU16(outfit.getId());
msg.addU8(outfit.getHead()); msg->addU8(outfit.getHead());
msg.addU8(outfit.getBody()); msg->addU8(outfit.getBody());
msg.addU8(outfit.getLegs()); msg->addU8(outfit.getLegs());
msg.addU8(outfit.getFeet()); msg->addU8(outfit.getFeet());
msg.addU8(outfit.getAddons()); msg->addU8(outfit.getAddons());
send(msg); send(msg);
} }
void ProtocolGame::sendMount(bool mount) void ProtocolGame::sendMount(bool mount)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientMount); msg->addU8(Proto::ClientMount);
msg.addU8(mount); msg->addU8(mount);
send(msg); send(msg);
} }
void ProtocolGame::sendAddVip(const std::string& name) void ProtocolGame::sendAddVip(const std::string& name)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientAddVip); msg->addU8(Proto::ClientAddVip);
msg.addString(name); msg->addString(name);
send(msg); send(msg);
} }
void ProtocolGame::sendRemoveVip(uint playerId) void ProtocolGame::sendRemoveVip(uint playerId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRemoveVip); msg->addU8(Proto::ClientRemoveVip);
msg.addU32(playerId); msg->addU32(playerId);
send(msg); send(msg);
} }
void ProtocolGame::sendBugReport(const std::string& comment) void ProtocolGame::sendBugReport(const std::string& comment)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientBugReport); msg->addU8(Proto::ClientBugReport);
msg.addString(comment); msg->addString(comment);
send(msg); send(msg);
} }
void ProtocolGame::sendRuleVilation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment) void ProtocolGame::sendRuleVilation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRuleViolation); msg->addU8(Proto::ClientRuleViolation);
msg.addString(target); msg->addString(target);
msg.addU8(reason); msg->addU8(reason);
msg.addU8(action); msg->addU8(action);
msg.addString(comment); msg->addString(comment);
msg.addString(statement); msg->addString(statement);
msg.addU16(statementId); msg->addU16(statementId);
msg.addU8(ipBanishment); msg->addU8(ipBanishment);
send(msg); send(msg);
} }
void ProtocolGame::sendDebugReport(const std::string& a, const std::string& b, const std::string& c, const std::string& d) void ProtocolGame::sendDebugReport(const std::string& a, const std::string& b, const std::string& c, const std::string& d)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientDebugReport); msg->addU8(Proto::ClientDebugReport);
msg.addString(a); msg->addString(a);
msg.addString(b); msg->addString(b);
msg.addString(c); msg->addString(c);
msg.addString(d); msg->addString(d);
send(msg); send(msg);
} }
void ProtocolGame::sendRequestQuestLog() void ProtocolGame::sendRequestQuestLog()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRequestQuestLog); msg->addU8(Proto::ClientRequestQuestLog);
send(msg); send(msg);
} }
void ProtocolGame::sendRequestQuestLine(int questId) void ProtocolGame::sendRequestQuestLine(int questId)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRequestQuestLine); msg->addU8(Proto::ClientRequestQuestLine);
msg.addU16(questId); msg->addU16(questId);
send(msg); send(msg);
} }
void ProtocolGame::sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation) void ProtocolGame::sendNewNewRuleViolation(int reason, int action, const std::string& characterName, const std::string& comment, const std::string& translation)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientNewRuleViolation); msg->addU8(Proto::ClientNewRuleViolation);
msg.addU8(reason); msg->addU8(reason);
msg.addU8(action); msg->addU8(action);
msg.addString(characterName); msg->addString(characterName);
msg.addString(comment); msg->addString(comment);
msg.addString(translation); msg->addString(translation);
send(msg); send(msg);
} }
void ProtocolGame::sendRequestItemInfo(int itemId, int index) void ProtocolGame::sendRequestItemInfo(int itemId, int index)
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientRequestItemInfo); msg->addU8(Proto::ClientRequestItemInfo);
msg.addU8(1); // count, 1 for just one item msg->addU8(1); // count, 1 for just one item
msg.addU16(itemId); msg->addU16(itemId);
msg.addU8(index); msg->addU8(index);
send(msg); send(msg);
} }
void ProtocolGame::sendExtendedOpcode(uint8 opcode, const std::string& buffer) void ProtocolGame::addPosition(const OutputMessagePtr& msg, const Position& position)
{ {
OutputMessage msg; msg->addU16(position.x);
msg.addU8(Proto::ClientExtendedOpcode); msg->addU16(position.y);
msg.addU8(opcode); msg->addU8(position.z);
msg.addString(buffer);
send(msg);
}
void ProtocolGame::addPosition(OutputMessage& msg, const Position& position)
{
msg.addU16(position.x);
msg.addU16(position.y);
msg.addU8(position.z);
} }

View File

@ -22,7 +22,6 @@
#include "protocollogin.h" #include "protocollogin.h"
#include <framework/net/outputmessage.h> #include <framework/net/outputmessage.h>
#include <framework/net/rsa.h>
#include <framework/luascript/luainterface.h> #include <framework/luascript/luainterface.h>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <otclient/core/thingstype.h> #include <otclient/core/thingstype.h>
@ -46,23 +45,23 @@ void ProtocolLogin::onConnect()
sendLoginPacket(); sendLoginPacket();
} }
void ProtocolLogin::onRecv(InputMessage& inputMessage) void ProtocolLogin::onRecv(const InputMessagePtr& msg)
{ {
try { try {
while(!inputMessage.eof()) { while(!msg->eof()) {
int opcode = inputMessage.getU8(); int opcode = msg->getU8();
switch(opcode) { switch(opcode) {
case Proto::LoginServerError: case Proto::LoginServerError:
parseError(inputMessage); parseError(msg);
break; break;
case Proto::LoginServerMotd: case Proto::LoginServerMotd:
parseMOTD(inputMessage); parseMOTD(msg);
break; break;
case Proto::LoginServerUpdateNeeded: case Proto::LoginServerUpdateNeeded:
callLuaField("onError", "Client needs update."); callLuaField("onError", "Client needs update.");
break; break;
case Proto::LoginServerCharacterList: case Proto::LoginServerCharacterList:
parseCharacterList(inputMessage); parseCharacterList(msg);
break; break;
default: default:
Fw::throwException("unknown opt byte ", opcode); Fw::throwException("unknown opt byte ", opcode);
@ -83,76 +82,76 @@ void ProtocolLogin::onError(const boost::system::error_code& error)
void ProtocolLogin::sendLoginPacket() void ProtocolLogin::sendLoginPacket()
{ {
OutputMessage msg; OutputMessagePtr msg(new OutputMessage);
msg.addU8(Proto::ClientEnterAccount); msg->addU8(Proto::ClientEnterAccount);
msg.addU16(Proto::ClientOs); msg->addU16(Proto::ClientOs);
msg.addU16(Proto::ClientVersion); msg->addU16(Proto::ClientVersion);
msg.addU32(g_thingsType.getSignature()); // data signature msg->addU32(g_thingsType.getSignature()); // data signature
msg.addU32(g_sprites.getSignature()); // sprite signature msg->addU32(g_sprites.getSignature()); // sprite signature
msg.addU32(Proto::PicSignature); // pic signature msg->addU32(Proto::PicSignature); // pic signature
int paddingBytes = 128; int paddingBytes = 128;
msg.addU8(0); // first RSA byte must be 0 msg->addU8(0); // first RSA byte must be 0
paddingBytes -= 1; paddingBytes -= 1;
// xtea key // xtea key
generateXteaKey(); generateXteaKey();
msg.addU32(m_xteaKey[0]); msg->addU32(m_xteaKey[0]);
msg.addU32(m_xteaKey[1]); msg->addU32(m_xteaKey[1]);
msg.addU32(m_xteaKey[2]); msg->addU32(m_xteaKey[2]);
msg.addU32(m_xteaKey[3]); msg->addU32(m_xteaKey[3]);
paddingBytes -= 16; paddingBytes -= 16;
#if PROTOCOL>=854 #if PROTOCOL>=854
enableChecksum(); enableChecksum();
msg.addString(m_accountName); msg->addString(m_accountName);
msg.addString(m_accountPassword); msg->addString(m_accountPassword);
paddingBytes -= 4 + m_accountName.length() + m_accountPassword.length(); paddingBytes -= 4 + m_accountName.length() + m_accountPassword.length();
#elif PROTOCOL>=810 #elif PROTOCOL>=810
msg.addU32(Fw::fromstring<uint32>(m_accountName)); msg->addU32(Fw::fromstring<uint32>(m_accountName));
msg.addString(m_accountPassword); msg->addString(m_accountPassword);
paddingBytes -= 6 + m_accountPassword.length(); paddingBytes -= 6 + m_accountPassword.length();
#endif #endif
msg.addPaddingBytes(paddingBytes); // complete the 128 bytes for rsa encryption with zeros msg->addPaddingBytes(paddingBytes); // complete the 128 bytes for rsa encryption with zeros
Rsa::encrypt((char*)msg.getWriteBuffer() - 128, 128, Proto::RSA); msg->encryptRSA(128, Proto::RSA);
send(msg); send(msg);
enableXteaEncryption(); enableXteaEncryption();
recv(); recv();
} }
void ProtocolLogin::parseError(InputMessage& inputMessage) void ProtocolLogin::parseError(const InputMessagePtr& msg)
{ {
std::string error = inputMessage.getString(); std::string error = msg->getString();
callLuaField("onError", error, false); callLuaField("onError", error, false);
} }
void ProtocolLogin::parseMOTD(InputMessage& inputMessage) void ProtocolLogin::parseMOTD(const InputMessagePtr& msg)
{ {
std::string motd = inputMessage.getString(); std::string motd = msg->getString();
callLuaField("onMotd", motd); callLuaField("onMotd", motd);
} }
void ProtocolLogin::parseCharacterList(InputMessage& inputMessage) void ProtocolLogin::parseCharacterList(const InputMessagePtr& msg)
{ {
typedef std::tuple<std::string, std::string, std::string, int> CharacterInfo; typedef std::tuple<std::string, std::string, std::string, int> CharacterInfo;
typedef std::vector<CharacterInfo> CharaterList; typedef std::vector<CharacterInfo> CharaterList;
CharaterList charList; CharaterList charList;
int numCharacters = inputMessage.getU8(); int numCharacters = msg->getU8();
for(int i = 0; i < numCharacters; ++i) { for(int i = 0; i < numCharacters; ++i) {
std::string name = inputMessage.getString(); std::string name = msg->getString();
std::string world = inputMessage.getString(); std::string world = msg->getString();
uint32 ip = inputMessage.getU32(); uint32 ip = msg->getU32();
uint16 port = inputMessage.getU16(); uint16 port = msg->getU16();
charList.push_back(CharacterInfo(name, world, Fw::ip2str(ip), port)); charList.push_back(CharacterInfo(name, world, Fw::ip2str(ip), port));
} }
int premDays = inputMessage.getU16(); int premDays = msg->getU16();
callLuaField("onCharacterList", charList, premDays); callLuaField("onCharacterList", charList, premDays);
} }

View File

@ -38,7 +38,7 @@ public:
void cancelLogin() { disconnect(); } void cancelLogin() { disconnect(); }
void onConnect(); void onConnect();
void onRecv(InputMessage& inputMessage); void onRecv(const InputMessagePtr& inputMessage);
void onError(const boost::system::error_code& error); void onError(const boost::system::error_code& error);
ProtocolLoginPtr asProtocolLogin() { return std::static_pointer_cast<ProtocolLogin>(shared_from_this()); } ProtocolLoginPtr asProtocolLogin() { return std::static_pointer_cast<ProtocolLogin>(shared_from_this()); }
@ -46,9 +46,9 @@ public:
private: private:
void sendLoginPacket(); void sendLoginPacket();
void parseError(InputMessage& inputMessage); void parseError(const InputMessagePtr& inputMessage);
void parseMOTD(InputMessage& inputMessage); void parseMOTD(const InputMessagePtr& inputMessage);
void parseCharacterList(InputMessage& inputMessage); void parseCharacterList(const InputMessagePtr& inputMessage);
std::string m_accountName, m_accountPassword; std::string m_accountName, m_accountPassword;