Skip to content

Commit

Permalink
SPX Protocol Support (with compress)
Browse files Browse the repository at this point in the history
  • Loading branch information
mehah authored Jan 26, 2023
1 parent 03cb989 commit 4e79004
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 6 deletions.
1 change: 1 addition & 0 deletions modules/gamelib/const.lua
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ GameThingUpgradeClassification = 86
GameThingCounter = 87
GameThingClock = 88
GameThingPodiumItemType = 89
GameSequencedPackets = 90
GameLoadSprInsteadProtobuf = 100

TextColors = {
Expand Down
8 changes: 8 additions & 0 deletions modules/gamelib/protocollogin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,17 @@ function ProtocolLogin:sendLoginPacket()
end

self:send(msg)

if g_game.getFeature(GameLoginPacketEncryption) then
self:enableXteaEncryption()
end

if g_game.getFeature(GameSequencedPackets) then
scheduleEvent(function()
self:enabledSequencedPackets()
end, 10)
end

self:recv()
end

Expand Down
1 change: 1 addition & 0 deletions src/client/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ namespace Otc
GameThingCounter = 87,
GameThingClock = 88,
GameThingPodiumItemType = 89,
GameSequencedPackets = 90,

// others
GameLoadSprInsteadProtobuf = 100,
Expand Down
4 changes: 2 additions & 2 deletions src/client/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -614,11 +614,10 @@ bool Game::walk(const Otc::Direction direction, bool isKeyDown /*= false*/)
m_localPlayer->lockWalk();
}


// must cancel follow before any new walk
if (isFollowing())
cancelFollow();

m_localPlayer->stopAutoWalk();

g_lua.callGlobalField("g_game", "onWalk", direction);
Expand Down Expand Up @@ -1739,6 +1738,7 @@ void Game::setClientVersion(int version)
}

if (version >= 1290) {
enableFeature(Otc::GameSequencedPackets);
enableFeature(Otc::GameThingClock);
enableFeature(Otc::GameThingCounter);
enableFeature(Otc::GameThingPodiumItemType);
Expand Down
3 changes: 3 additions & 0 deletions src/client/protocolgamesend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ void ProtocolGame::sendLoginPacket(uint32_t challengeTimestamp, uint8_t challeng

if (g_game.getFeature(Otc::GameLoginPacketEncryption))
enableXteaEncryption();

if (g_game.getFeature(Otc::GameSequencedPackets))
enabledSequencedPackets();
}

void ProtocolGame::sendEnterGame()
Expand Down
1 change: 1 addition & 0 deletions src/framework/luafunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,7 @@ void Application::registerLuaFunctions()
g_lua.bindClassMemberFunction<Protocol>("getXteaKey", &Protocol::getXteaKey);
g_lua.bindClassMemberFunction<Protocol>("generateXteaKey", &Protocol::generateXteaKey);
g_lua.bindClassMemberFunction<Protocol>("enableXteaEncryption", &Protocol::enableXteaEncryption);
g_lua.bindClassMemberFunction<Protocol>("enabledSequencedPackets", &Protocol::enabledSequencedPackets);
g_lua.bindClassMemberFunction<Protocol>("enableChecksum", &Protocol::enableChecksum);

// InputMessage
Expand Down
8 changes: 8 additions & 0 deletions src/framework/net/outputmessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ void OutputMessage::writeChecksum()
m_messageSize += 4;
}

void OutputMessage::writeSequence(uint32_t sequence)
{
assert(m_headerPos >= 4);
m_headerPos -= 4;
stdext::writeULE32(m_buffer + m_headerPos, sequence);
m_messageSize += 4;
}

void OutputMessage::writeMessageSize()
{
assert(m_headerPos - 2 >= 0);
Expand Down
1 change: 1 addition & 0 deletions src/framework/net/outputmessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class OutputMessage : public LuaObject
uint8_t* getDataBuffer() { return m_buffer + MAX_HEADER_SIZE; }

void writeChecksum();
void writeSequence(uint32_t sequence);
void writeMessageSize();

friend class Protocol;
Expand Down
42 changes: 38 additions & 4 deletions src/framework/net/protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@
#include <framework/core/application.h>
#include "connection.h"

Protocol::Protocol() :m_inputMessage(std::make_shared<InputMessage>()) {}
Protocol::Protocol() :m_inputMessage(std::make_shared<InputMessage>()) {
inflateInit2(&m_zstream, -15);
}

Protocol::~Protocol()
{
#ifndef NDEBUG
assert(!g_app.isTerminated());
#endif
disconnect();
inflateEnd(&m_zstream);
}

void Protocol::connect(const std::string_view host, uint16_t port)
Expand All @@ -57,7 +60,9 @@ void Protocol::send(const OutputMessagePtr& outputMessage)
xteaEncrypt(outputMessage);

// write checksum
if (m_checksumEnabled)
if (m_sequencedPackets)
outputMessage->writeSequence(m_packetNumber++);
else if (m_checksumEnabled)
outputMessage->writeChecksum();

// write message size
Expand Down Expand Up @@ -115,8 +120,11 @@ void Protocol::internalRecvData(uint8_t* buffer, uint16_t size)

m_inputMessage->fillBuffer(buffer, size);

if (m_checksumEnabled && !m_inputMessage->readChecksum()) {
g_logger.traceError("got a network message with invalid checksum");
bool decompress = false;
if (m_sequencedPackets) {
decompress = (m_inputMessage->getU32() & 1 << 31);
} else if (m_checksumEnabled && !m_inputMessage->readChecksum()) {
g_logger.traceError(stdext::format("got a network message with invalid checksum, size: %i", (int)m_inputMessage->getMessageSize()));
return;
}

Expand All @@ -126,6 +134,32 @@ void Protocol::internalRecvData(uint8_t* buffer, uint16_t size)
return;
}
}

if (decompress) {
static uint8_t zbuffer[InputMessage::BUFFER_MAXSIZE];

m_zstream.next_in = m_inputMessage->getDataBuffer();
m_zstream.next_out = zbuffer;
m_zstream.avail_in = m_inputMessage->getUnreadSize();
m_zstream.avail_out = InputMessage::BUFFER_MAXSIZE;

int32_t ret = inflate(&m_zstream, Z_FINISH);
if (ret != Z_OK && ret != Z_STREAM_END) {
g_logger.traceError(stdext::format("failed to decompress message - %s", m_zstream.msg));
return;
}

const uint32_t totalSize = m_zstream.total_out;
inflateReset(&m_zstream);
if (totalSize == 0) {
g_logger.traceError(stdext::format("invalid size of decompressed message - %i", totalSize));
return;
}

m_inputMessage->fillBuffer(zbuffer, totalSize);
m_inputMessage->setMessageSize(m_inputMessage->getHeaderSize() + totalSize);
}

onRecv(m_inputMessage);
}

Expand Down
7 changes: 7 additions & 0 deletions src/framework/net/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "outputmessage.h"

#include <framework/luaengine/luaobject.h>
#include <zlib.h>

// @bindclass
class Protocol : public LuaObject
Expand All @@ -52,6 +53,7 @@ class Protocol : public LuaObject
void enableXteaEncryption() { m_xteaEncryptionEnabled = true; }

void enableChecksum() { m_checksumEnabled = true; }
void enabledSequencedPackets() { m_sequencedPackets = true; }

virtual void send(const OutputMessagePtr& outputMessage);
virtual void recv();
Expand All @@ -64,6 +66,7 @@ class Protocol : public LuaObject
virtual void onError(const std::error_code& err);

std::array<uint32_t, 4> m_xteaKey{};
uint32_t m_packetNumber{ 0 };

private:
void internalRecvHeader(uint8_t* buffer, uint16_t size);
Expand All @@ -73,7 +76,11 @@ class Protocol : public LuaObject
void xteaEncrypt(const OutputMessagePtr& outputMessage) const;

bool m_checksumEnabled{ false };
bool m_sequencedPackets{ false };
bool m_xteaEncryptionEnabled{ false };

ConnectionPtr m_connection;
InputMessagePtr m_inputMessage;

z_stream m_zstream{};
};

0 comments on commit 4e79004

Please sign in to comment.