make sc ommand work on game server also

This commit is contained in:
Martin Michelsen
2022-05-22 10:50:50 -07:00
parent 37a7faf007
commit a50500a67d
9 changed files with 74 additions and 26 deletions
+3 -5
View File
@@ -77,10 +77,8 @@ string IPStackSimulator::str_for_tcp_connection(shared_ptr<const IPClient> c,
IPStackSimulator::IPStackSimulator(
std::shared_ptr<struct event_base> base,
std::shared_ptr<Server> game_server,
std::shared_ptr<ServerState> state)
: base(base),
game_server(game_server),
state(state),
pcap_text_log_file(state->ip_stack_debug ? fopen("IPStackSimulator-Log.txt", "wt") : nullptr) {
memset(this->host_mac_address_bytes, 0x90, 6);
@@ -779,9 +777,9 @@ void IPStackSimulator::open_server_connection(
this->log(INFO, "Connected TCP connection %s to proxy server",
conn_str.c_str());
}
} else if (this->game_server.get()) {
this->game_server->connect_client(bevs[1], c->ipv4_addr, conn.client_port,
port_config->version, port_config->behavior);
} else if (this->state->game_server.get()) {
this->state->game_server->connect_client(bevs[1], c->ipv4_addr,
conn.client_port, port_config->version, port_config->behavior);
this->log(INFO, "Connected TCP connection %s to game server",
conn_str.c_str());
} else {
-2
View File
@@ -17,7 +17,6 @@ class IPStackSimulator {
public:
IPStackSimulator(
std::shared_ptr<struct event_base> base,
std::shared_ptr<Server> game_server,
std::shared_ptr<ServerState> state);
~IPStackSimulator();
@@ -31,7 +30,6 @@ public:
private:
static PrefixedLogger log;
std::shared_ptr<struct event_base> base;
std::shared_ptr<Server> game_server;
std::shared_ptr<ServerState> state;
using unique_listener = std::unique_ptr<struct evconnlistener, void(*)(struct evconnlistener*)>;
+4 -7
View File
@@ -444,8 +444,6 @@ int main(int argc, char** argv) {
log(INFO, "DNS server is disabled");
}
shared_ptr<Server> game_server;
log(INFO, "Opening sockets");
for (const auto& it : state->name_to_port_config) {
const auto& pc = it.second;
@@ -475,22 +473,21 @@ int main(int argc, char** argv) {
}
}
} else {
if (!game_server.get()) {
if (!state->game_server.get()) {
log(INFO, "Starting game server");
game_server.reset(new Server(base, state));
state->game_server.reset(new Server(base, state));
}
string name = string_printf("%s (%s, %s) on port %hu",
pc->name.c_str(), name_for_version(pc->version),
name_for_server_behavior(pc->behavior), pc->port);
game_server->listen(name, "", pc->port, pc->version, pc->behavior);
state->game_server->listen(name, "", pc->port, pc->version, pc->behavior);
}
}
shared_ptr<IPStackSimulator> ip_stack_simulator;
if (!state->ip_stack_addresses.empty()) {
log(INFO, "Starting IP stack simulator");
ip_stack_simulator.reset(new IPStackSimulator(
base, game_server, state));
ip_stack_simulator.reset(new IPStackSimulator(base, state));
for (const auto& it : state->ip_stack_addresses) {
auto netloc = parse_netloc(it);
ip_stack_simulator->listen(netloc.first, netloc.second);
+30 -3
View File
@@ -153,6 +153,33 @@ void send_command(shared_ptr<ServerState> s, uint16_t command, uint32_t flag,
}
}
template <typename HeaderT>
void send_command_with_header_t(shared_ptr<Client> c, const void* data,
size_t size) {
const HeaderT* header = reinterpret_cast<const HeaderT*>(data);
send_command(c, header->command, header->flag, header + 1, size - sizeof(HeaderT));
}
void send_command_with_header(shared_ptr<Client> c, const void* data,
size_t size) {
switch (c->version) {
case GameVersion::GC:
case GameVersion::DC:
send_command_with_header_t<PSOCommandHeaderDCGC>(c, data, size);
break;
case GameVersion::PC:
case GameVersion::PATCH:
send_command_with_header_t<PSOCommandHeaderPC>(c, data, size);
break;
case GameVersion::BB:
send_command_with_header_t<PSOCommandHeaderBB>(c, data, size);
break;
default:
throw logic_error("unimplemented game version in send_command_with_header");
}
}
// specific command sending functions follow. in general, they're written in
@@ -540,7 +567,7 @@ void send_chat_message(shared_ptr<Client> c, uint32_t from_guild_card_number,
send_header_text(c, 0x06, from_guild_card_number, data);
}
void send_simple_mail_gc(std::shared_ptr<Client> c, uint32_t from_guild_card_number,
void send_simple_mail_gc(shared_ptr<Client> c, uint32_t from_guild_card_number,
const u16string& from_name, const u16string& text) {
SC_SimpleMail_GC_81 cmd;
cmd.player_tag = 0x00010000;
@@ -551,7 +578,7 @@ void send_simple_mail_gc(std::shared_ptr<Client> c, uint32_t from_guild_card_num
send_command_t(c, 0x81, 0x00, cmd);
}
void send_simple_mail(std::shared_ptr<Client> c, uint32_t from_guild_card_number,
void send_simple_mail(shared_ptr<Client> c, uint32_t from_guild_card_number,
const u16string& from_name, const u16string& text) {
if (c->version == GameVersion::GC) {
send_simple_mail_gc(c, from_guild_card_number, from_name, text);
@@ -852,7 +879,7 @@ void send_quest_menu(shared_ptr<Client> c, uint32_t menu_id,
}
void send_quest_menu(shared_ptr<Client> c, uint32_t menu_id,
const std::vector<MenuItem>& items, bool is_download_menu) {
const vector<MenuItem>& items, bool is_download_menu) {
if (c->version == GameVersion::PC) {
send_quest_menu_t<S_QuestMenuEntry_PC_A2_A4>(c, menu_id, items, is_download_menu);
} else if (c->version == GameVersion::GC) {
+5 -2
View File
@@ -22,8 +22,8 @@
// command to one client, sometimes to everyone in a lobby, etc.)
// - For the const void* versions, the data and size arguments should not be
// independently optional - this can lead to bugs where a non-null data
// pointer is given but size is accidentally not given zero (e.g. if the type
// of data in the calling function is changed from string to void*).
// pointer is given but size is accidentally not given (e.g. if the type of
// data in the calling function is changed from string to void*).
void send_command(struct bufferevent* bev, GameVersion version,
PSOEncryption* crypt, uint16_t command, uint32_t flag, const void* data,
@@ -88,6 +88,9 @@ void send_command_t_vt(std::shared_ptr<TargetT> c, uint16_t command,
send_command(c, command, flag, all_data.data(), all_data.size());
}
void send_command_with_header(std::shared_ptr<Client> c, const void* data,
size_t size);
S_ServerInit_DC_PC_GC_02_17 prepare_server_init_contents_dc_pc_gc(
+10
View File
@@ -273,3 +273,13 @@ void Server::add_socket(
this->listening_sockets.emplace(piecewise_construct, forward_as_tuple(fd),
forward_as_tuple(this, name, fd, version, behavior));
}
shared_ptr<Client> Server::get_client() const {
if (this->bev_to_client.empty()) {
throw runtime_error("no clients on game server");
}
if (this->bev_to_client.size() > 1) {
throw runtime_error("multiple clients on game server");
}
return this->bev_to_client.begin()->second;
}
+2
View File
@@ -29,6 +29,8 @@ public:
void connect_client(struct bufferevent* bev, uint32_t address, uint16_t port,
GameVersion version, ServerBehavior initial_state);
std::shared_ptr<Client> get_client() const;
private:
PrefixedLogger log;
std::shared_ptr<struct event_base> base;
+17 -4
View File
@@ -280,9 +280,6 @@ Proxy commands (these will only work when exactly one client is connected):\n\
// PROXY COMMANDS
} else if ((command_name == "sc") || (command_name == "ss")) {
auto session = this->get_proxy_session();
bool to_server = (command_name[1] == 's');
string data = parse_data_string(command_args);
if (data.size() & 3) {
throw invalid_argument("data size is not a multiple of 4");
@@ -291,7 +288,23 @@ Proxy commands (these will only work when exactly one client is connected):\n\
throw invalid_argument("no data given");
}
session->send_to_end_with_header(to_server, data);
shared_ptr<ProxyServer::LinkedSession> proxy_session;
try {
proxy_session = this->get_proxy_session();
} catch (const exception&) { }
if (proxy_session.get()) {
bool to_server = (command_name[1] == 's');
proxy_session->send_to_end_with_header(to_server, data);
} else {
if (command_name [1] == 's') {
throw runtime_error("cannot send to server in non-proxy session");
}
auto c = this->state->game_server->get_client();
send_command_with_header(c, data.data(), data.size());
}
} else if ((command_name == "chat") || (command_name == "dchat")) {
auto session = this->get_proxy_session();
+3 -3
View File
@@ -18,8 +18,9 @@
// Forwawrd declaration due to reference cycle
// Forwawrd declarations due to reference cycles
class ProxyServer;
class Server;
struct PortConfiguration {
std::string name;
@@ -76,9 +77,8 @@ struct ServerState {
uint32_t local_address;
uint32_t external_address;
// TODO: This is only here because the menu selection handler has to call
// delete_session on it. Find a cleaner way to do this.
std::shared_ptr<ProxyServer> proxy_server;
std::shared_ptr<Server> game_server;
ServerState();