make sc ommand work on game server also
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user