Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unknown packet handling in Lua #4043

Merged
merged 8 commits into from
Mar 28, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data/events/events.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<event class="Player" method="onGainSkillTries" enabled="1" />
<event class="Player" method="onWrapItem" enabled="1" />
<event class="Player" method="onInventoryUpdate" enabled="1" />
<event class="Player" method="onNetworkMessage" enabled="1" />

<!-- Monster methods -->
<event class="Monster" method="onDropLoot" enabled="1" />
Expand Down
10 changes: 10 additions & 0 deletions data/events/scripts/player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,13 @@ function Player:onInventoryUpdate(item, slot, equip)
EventCallback.onInventoryUpdate(self, item, slot, equip)
end
end

function Player:onNetworkMessage(recvByte, msg)
local handler = PacketHandlers[recvByte]
if not handler then
io.write(string.format("Player: %s sent an unknown packet header: 0x%02X with %d bytes!\n", self:getName(), recvByte, msg:len()))
return
end

handler(self, msg)
end
1 change: 1 addition & 0 deletions data/lib/core/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dofile('data/lib/core/creature.lua')
dofile('data/lib/core/game.lua')
dofile('data/lib/core/item.lua')
dofile('data/lib/core/itemtype.lua')
dofile('data/lib/core/packet_handler.lua')
dofile('data/lib/core/party.lua')
dofile('data/lib/core/player.lua')
dofile('data/lib/core/podium.lua')
Expand Down
29 changes: 29 additions & 0 deletions data/lib/core/packet_handler.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
PacketHandlers = {}

local function register(self)
if isScriptsInterface() then
if not self.onReceive then
debugPrint("[Warning - PacketHandler::register] need to setup a callback before you can register.")
return
end

if type(self.onReceive) ~= "function" then
debugPrint(string.format("[Warning - PacketHandler::onReceive] a function is expected."))
return
end

PacketHandlers[self.packetType] = self.onReceive
end
end

local function clear(self)
PacketHandlers[self.packetType] = nil
end

function PacketHandler(packetType)
return {
clear = clear,
packetType = packetType,
register = register,
}
end
31 changes: 31 additions & 0 deletions src/events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ bool Events::load()
info.playerOnWrapItem = event;
} else if (methodName == "onInventoryUpdate") {
info.playerOnInventoryUpdate = event;
} else if (methodName == "onNetworkMessage") {
info.playerOnNetworkMessage = event;
} else {
std::cout << "[Warning - Events::load] Unknown player method: " << methodName << std::endl;
}
Expand Down Expand Up @@ -1117,6 +1119,35 @@ void Events::eventPlayerOnInventoryUpdate(Player* player, Item* item, slots_t sl
scriptInterface.callVoidFunction(4);
}

void Events::eventPlayerOnNetworkMessage(Player* player, uint8_t recvByte, NetworkMessage* msg)
{
// Player:onNetworkMessage(recvByte, msg)
if (info.playerOnNetworkMessage == -1) {
return;
}

if (!scriptInterface.reserveScriptEnv()) {
std::cout << "[Error - Events::eventPlayerOnInventoryUpdate] Call stack overflow" << std::endl;
ranisalt marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eventPlayerOnNetworkMessage

return;
}

ScriptEnvironment* env = scriptInterface.getScriptEnv();
env->setScriptId(info.playerOnNetworkMessage, &scriptInterface);

lua_State* L = scriptInterface.getLuaState();
scriptInterface.pushFunction(info.playerOnNetworkMessage);

LuaScriptInterface::pushUserdata<Player>(L, player);
LuaScriptInterface::setMetatable(L, -1, "Player");

lua_pushnumber(L, recvByte);

LuaScriptInterface::pushUserdata<NetworkMessage>(L, msg);
LuaScriptInterface::setMetatable(L, -1, "NetworkMessage");

scriptInterface.callVoidFunction(3);
}

void Events::eventMonsterOnDropLoot(Monster* monster, Container* corpse)
{
// Monster:onDropLoot(corpse)
Expand Down
3 changes: 3 additions & 0 deletions src/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "luascript.h"

class ItemType;
class NetworkMessage;
class Party;
class Tile;

Expand Down Expand Up @@ -56,6 +57,7 @@ class Events
int32_t playerOnGainSkillTries = -1;
int32_t playerOnWrapItem = -1;
int32_t playerOnInventoryUpdate = -1;
int32_t playerOnNetworkMessage = -1;

// Monster
int32_t monsterOnDropLoot = -1;
Expand Down Expand Up @@ -109,6 +111,7 @@ class Events
void eventPlayerOnGainSkillTries(Player* player, skills_t skill, uint64_t& tries);
void eventPlayerOnWrapItem(Player* player, Item* item);
void eventPlayerOnInventoryUpdate(Player* player, Item* item, slots_t slot, bool equip);
void eventPlayerOnNetworkMessage(Player* player, uint8_t recvByte, NetworkMessage* msg);

// Monster
void eventMonsterOnDropLoot(Monster* monster, Container* corpse);
Expand Down
10 changes: 10 additions & 0 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5650,6 +5650,16 @@ void Game::parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const st
}
}

void Game::parsePlayerNetworkMessage(uint32_t playerId, uint8_t recvByte, NetworkMessage* msg)
{
Player* player = getPlayerByID(playerId);
if (!player) {
return;
}

g_events->eventPlayerOnNetworkMessage(player, recvByte, msg);
}

std::vector<Item*> Game::getMarketItemList(uint16_t wareId, uint16_t sufficientCount, const Player& player)
{
uint16_t count = 0;
Expand Down
1 change: 1 addition & 0 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ class Game
void playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16_t counter, uint16_t amount);

void parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const std::string& buffer);
void parsePlayerNetworkMessage(uint32_t playerId, uint8_t recvByte, NetworkMessage* msg);

std::vector<Item*> getMarketItemList(uint16_t wareId, uint16_t sufficientCount, const Player& player);

Expand Down
10 changes: 5 additions & 5 deletions src/networkmessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ std::string_view NetworkMessage::getString(uint16_t stringLen /* = 0*/)
return {};
}

char* v = reinterpret_cast<char*>(buffer) + info.position; // does not break strict aliasing
auto it = buffer.data() + info.position;
info.position += stringLen;
return {v, stringLen};
return {it, it + stringLen};
}

Position NetworkMessage::getPosition()
Expand All @@ -40,7 +40,7 @@ void NetworkMessage::addString(std::string_view value)
}

add<uint16_t>(stringLen);
memcpy(buffer + info.position, value.data(), stringLen);
std::memcpy(buffer.data() + info.position, value.data(), stringLen);
info.position += stringLen;
info.length += stringLen;
}
Expand All @@ -58,7 +58,7 @@ void NetworkMessage::addBytes(const char* bytes, size_t size)
return;
}

memcpy(buffer + info.position, bytes, size);
std::memcpy(buffer.data() + info.position, bytes, size);
info.position += size;
info.length += size;
}
Expand All @@ -69,7 +69,7 @@ void NetworkMessage::addPaddingBytes(size_t n)
return;
}

memset(buffer + info.position, 0x33, n);
std::fill_n(buffer.data() + info.position, n, 0x33);
info.length += n;
}

Expand Down
20 changes: 11 additions & 9 deletions src/networkmessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,18 @@ class NetworkMessage
uint8_t getPreviousByte() { return buffer[--info.position]; }

template <typename T>
T get()
std::enable_if_t<std::is_trivially_copyable_v<T>, T> get() noexcept
{
static_assert(std::is_trivially_constructible_v<T>, "Destination type must be trivially constructible");

if (!canRead(sizeof(T))) {
return 0;
}

T v;
memcpy(&v, buffer + info.position, sizeof(T));
T value;
std::memcpy(&value, buffer.data() + info.position, sizeof(T));
info.position += sizeof(T);
return v;
return value;
}

std::string_view getString(uint16_t stringLen = 0);
Expand All @@ -92,7 +94,7 @@ class NetworkMessage
return;
}

memcpy(buffer + info.position, &value, sizeof(T));
std::memcpy(buffer.data() + info.position, &value, sizeof(T));
info.position += sizeof(T);
info.length += sizeof(T);
}
Expand Down Expand Up @@ -129,14 +131,14 @@ class NetworkMessage

bool isOverrun() const { return info.overrun; }

uint8_t* getBuffer() { return buffer; }
uint8_t* getBuffer() { return &buffer[0]; }

const uint8_t* getBuffer() const { return buffer; }
const uint8_t* getBuffer() const { return &buffer[0]; }

uint8_t* getBodyBuffer()
{
info.position = 2;
return buffer + HEADER_LENGTH;
return &buffer[HEADER_LENGTH];
}

protected:
Expand All @@ -148,7 +150,7 @@ class NetworkMessage
};

NetworkMessageInfo info;
uint8_t buffer[NETWORKMESSAGE_MAXSIZE];
std::array<uint8_t, NETWORKMESSAGE_MAXSIZE> buffer;

private:
bool canAdd(size_t size) const { return (size + info.position) < MAX_BODY_LENGTH; }
Expand Down
10 changes: 5 additions & 5 deletions src/outputmessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ class OutputMessage : public NetworkMessage
OutputMessage(const OutputMessage&) = delete;
OutputMessage& operator=(const OutputMessage&) = delete;

uint8_t* getOutputBuffer() { return buffer + outputBufferStart; }
uint8_t* getOutputBuffer() { return &buffer[outputBufferStart]; }

void writeMessageLength() { add_header(info.length); }

void addCryptoHeader(checksumMode_t mode, uint32_t& sequence)
{
if (mode == CHECKSUM_ADLER) {
add_header(adlerChecksum(buffer + outputBufferStart, info.length));
add_header(adlerChecksum(&buffer[outputBufferStart], info.length));
} else if (mode == CHECKSUM_SEQUENCE) {
add_header(sequence++);
}
Expand All @@ -35,15 +35,15 @@ class OutputMessage : public NetworkMessage
void append(const NetworkMessage& msg)
{
auto msgLen = msg.getLength();
memcpy(buffer + info.position, msg.getBuffer() + 8, msgLen);
std::memcpy(buffer.data() + info.position, msg.getBuffer() + 8, msgLen);
info.length += msgLen;
info.position += msgLen;
}

void append(const OutputMessage_ptr& msg)
{
auto msgLen = msg->getLength();
memcpy(buffer + info.position, msg->getBuffer() + 8, msgLen);
std::memcpy(buffer.data() + info.position, msg->getBuffer() + 8, msgLen);
info.length += msgLen;
info.position += msgLen;
}
Expand All @@ -54,7 +54,7 @@ class OutputMessage : public NetworkMessage
{
assert(outputBufferStart >= sizeof(T));
outputBufferStart -= sizeof(T);
memcpy(buffer + outputBufferStart, &add, sizeof(T));
std::memcpy(buffer.data() + outputBufferStart, &add, sizeof(T));
// added header size to the message size
info.length += sizeof(T);
}
Expand Down
5 changes: 3 additions & 2 deletions src/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,8 +847,9 @@ void ProtocolGame::parsePacket(NetworkMessage& msg)
// case 0xFE: break; // store window history 2

default:
// std::cout << "Player: " << player->getName() << " sent an unknown packet header: 0x" << std::hex <<
// static_cast<uint16_t>(recvbyte) << std::dec << "!" << std::endl;
g_dispatcher.addTask([=, playerID = player->getID(), msg = new NetworkMessage(msg)]() {
g_game.parsePlayerNetworkMessage(playerID, recvbyte, msg);
});
break;
}

Expand Down