handle multiple subcommands in one top-level command

This commit is contained in:
Martin Michelsen
2023-06-18 22:56:20 -07:00
parent dcbfeebc37
commit 24c5ad1d06
3 changed files with 31 additions and 10 deletions
+1 -1
View File
@@ -2533,7 +2533,7 @@ static void on_6x_C9_CB(shared_ptr<ServerState> s, shared_ptr<Client> c,
return; return;
} }
on_subcommand(s, l, c, command, flag, data); on_subcommand_multi(s, l, c, command, flag, data);
} }
static void on_chat_generic(shared_ptr<ServerState> s, shared_ptr<Client> c, static void on_chat_generic(shared_ptr<ServerState> s, shared_ptr<Client> c,
+27 -6
View File
@@ -1714,21 +1714,42 @@ subcommand_handler_t subcommand_handlers[0x100] = {
/* 6xFF */ nullptr, /* 6xFF */ nullptr,
}; };
void on_subcommand(shared_ptr<ServerState> s, shared_ptr<Lobby> l, void on_subcommand_multi(shared_ptr<ServerState> s, shared_ptr<Lobby> l,
shared_ptr<Client> c, uint8_t command, uint8_t flag, const string& data) { shared_ptr<Client> c, uint8_t command, uint8_t flag, const string& data) {
if (data.empty()) { if (data.empty()) {
throw runtime_error("game command is empty"); throw runtime_error("game command is empty");
} }
if (c->version() == GameVersion::DC && (c->flags & (Client::Flag::IS_TRIAL_EDITION | Client::Flag::IS_DC_V1_PROTOTYPE))) { if (c->version() == GameVersion::DC && (c->flags & (Client::Flag::IS_TRIAL_EDITION | Client::Flag::IS_DC_V1_PROTOTYPE))) {
// TODO: We should convert these to non-trial formats and vice versa // TODO: We should convert these to non-trial formats and vice versa
forward_subcommand(l, c, command, flag, std::move(data)); forward_subcommand(l, c, command, flag, data.data(), data.size());
} else { } else {
uint8_t which = static_cast<uint8_t>(data[0]); StringReader r(data);
auto fn = subcommand_handlers[which]; while (!r.eof()) {
size_t size;
const auto& header = r.get<G_UnusedHeader>(false);
if (header.size != 0) {
size = header.size << 2;
} else {
const auto& ext_header = r.get<G_ExtendedHeader<G_UnusedHeader>>(false);
size = ext_header.size;
if (size < 8) {
throw runtime_error("extended subcommand header has size < 8");
}
if (size & 3) {
throw runtime_error("extended subcommand size is not a multiple of 4");
}
}
if (size == 0) {
throw runtime_error("invalid subcommand size");
}
const void* data = r.getv(size);
auto fn = subcommand_handlers[header.subcommand];
if (fn) { if (fn) {
fn(s, l, c, command, flag, data); fn(s, l, c, command, flag, data, size);
} else { } else {
on_unimplemented(s, l, c, command, flag, data); on_unimplemented(s, l, c, command, flag, data, size);
}
} }
} }
} }
+1 -1
View File
@@ -5,7 +5,7 @@
#include "PSOProtocol.hh" #include "PSOProtocol.hh"
#include "ServerState.hh" #include "ServerState.hh"
void on_subcommand( void on_subcommand_multi(
std::shared_ptr<ServerState> s, std::shared_ptr<Lobby> l, std::shared_ptr<ServerState> s, std::shared_ptr<Lobby> l,
std::shared_ptr<Client> c, uint8_t command, uint8_t flag, std::shared_ptr<Client> c, uint8_t command, uint8_t flag,
const std::string& data); const std::string& data);