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(
|
IPStackSimulator::IPStackSimulator(
|
||||||
std::shared_ptr<struct event_base> base,
|
std::shared_ptr<struct event_base> base,
|
||||||
std::shared_ptr<Server> game_server,
|
|
||||||
std::shared_ptr<ServerState> state)
|
std::shared_ptr<ServerState> state)
|
||||||
: base(base),
|
: base(base),
|
||||||
game_server(game_server),
|
|
||||||
state(state),
|
state(state),
|
||||||
pcap_text_log_file(state->ip_stack_debug ? fopen("IPStackSimulator-Log.txt", "wt") : nullptr) {
|
pcap_text_log_file(state->ip_stack_debug ? fopen("IPStackSimulator-Log.txt", "wt") : nullptr) {
|
||||||
memset(this->host_mac_address_bytes, 0x90, 6);
|
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",
|
this->log(INFO, "Connected TCP connection %s to proxy server",
|
||||||
conn_str.c_str());
|
conn_str.c_str());
|
||||||
}
|
}
|
||||||
} else if (this->game_server.get()) {
|
} else if (this->state->game_server.get()) {
|
||||||
this->game_server->connect_client(bevs[1], c->ipv4_addr, conn.client_port,
|
this->state->game_server->connect_client(bevs[1], c->ipv4_addr,
|
||||||
port_config->version, port_config->behavior);
|
conn.client_port, port_config->version, port_config->behavior);
|
||||||
this->log(INFO, "Connected TCP connection %s to game server",
|
this->log(INFO, "Connected TCP connection %s to game server",
|
||||||
conn_str.c_str());
|
conn_str.c_str());
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ class IPStackSimulator {
|
|||||||
public:
|
public:
|
||||||
IPStackSimulator(
|
IPStackSimulator(
|
||||||
std::shared_ptr<struct event_base> base,
|
std::shared_ptr<struct event_base> base,
|
||||||
std::shared_ptr<Server> game_server,
|
|
||||||
std::shared_ptr<ServerState> state);
|
std::shared_ptr<ServerState> state);
|
||||||
~IPStackSimulator();
|
~IPStackSimulator();
|
||||||
|
|
||||||
@@ -31,7 +30,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
static PrefixedLogger log;
|
static PrefixedLogger log;
|
||||||
std::shared_ptr<struct event_base> base;
|
std::shared_ptr<struct event_base> base;
|
||||||
std::shared_ptr<Server> game_server;
|
|
||||||
std::shared_ptr<ServerState> state;
|
std::shared_ptr<ServerState> state;
|
||||||
|
|
||||||
using unique_listener = std::unique_ptr<struct evconnlistener, void(*)(struct evconnlistener*)>;
|
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");
|
log(INFO, "DNS server is disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<Server> game_server;
|
|
||||||
|
|
||||||
log(INFO, "Opening sockets");
|
log(INFO, "Opening sockets");
|
||||||
for (const auto& it : state->name_to_port_config) {
|
for (const auto& it : state->name_to_port_config) {
|
||||||
const auto& pc = it.second;
|
const auto& pc = it.second;
|
||||||
@@ -475,22 +473,21 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!game_server.get()) {
|
if (!state->game_server.get()) {
|
||||||
log(INFO, "Starting game server");
|
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",
|
string name = string_printf("%s (%s, %s) on port %hu",
|
||||||
pc->name.c_str(), name_for_version(pc->version),
|
pc->name.c_str(), name_for_version(pc->version),
|
||||||
name_for_server_behavior(pc->behavior), pc->port);
|
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;
|
shared_ptr<IPStackSimulator> ip_stack_simulator;
|
||||||
if (!state->ip_stack_addresses.empty()) {
|
if (!state->ip_stack_addresses.empty()) {
|
||||||
log(INFO, "Starting IP stack simulator");
|
log(INFO, "Starting IP stack simulator");
|
||||||
ip_stack_simulator.reset(new IPStackSimulator(
|
ip_stack_simulator.reset(new IPStackSimulator(base, state));
|
||||||
base, game_server, state));
|
|
||||||
for (const auto& it : state->ip_stack_addresses) {
|
for (const auto& it : state->ip_stack_addresses) {
|
||||||
auto netloc = parse_netloc(it);
|
auto netloc = parse_netloc(it);
|
||||||
ip_stack_simulator->listen(netloc.first, netloc.second);
|
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
|
// 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);
|
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) {
|
const u16string& from_name, const u16string& text) {
|
||||||
SC_SimpleMail_GC_81 cmd;
|
SC_SimpleMail_GC_81 cmd;
|
||||||
cmd.player_tag = 0x00010000;
|
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);
|
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) {
|
const u16string& from_name, const u16string& text) {
|
||||||
if (c->version == GameVersion::GC) {
|
if (c->version == GameVersion::GC) {
|
||||||
send_simple_mail_gc(c, from_guild_card_number, from_name, text);
|
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,
|
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) {
|
if (c->version == GameVersion::PC) {
|
||||||
send_quest_menu_t<S_QuestMenuEntry_PC_A2_A4>(c, menu_id, items, is_download_menu);
|
send_quest_menu_t<S_QuestMenuEntry_PC_A2_A4>(c, menu_id, items, is_download_menu);
|
||||||
} else if (c->version == GameVersion::GC) {
|
} else if (c->version == GameVersion::GC) {
|
||||||
|
|||||||
+5
-2
@@ -22,8 +22,8 @@
|
|||||||
// command to one client, sometimes to everyone in a lobby, etc.)
|
// command to one client, sometimes to everyone in a lobby, etc.)
|
||||||
// - For the const void* versions, the data and size arguments should not be
|
// - 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
|
// 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
|
// pointer is given but size is accidentally not given (e.g. if the type of
|
||||||
// of data in the calling function is changed from string to void*).
|
// data in the calling function is changed from string to void*).
|
||||||
|
|
||||||
void send_command(struct bufferevent* bev, GameVersion version,
|
void send_command(struct bufferevent* bev, GameVersion version,
|
||||||
PSOEncryption* crypt, uint16_t command, uint32_t flag, const void* data,
|
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());
|
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(
|
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),
|
this->listening_sockets.emplace(piecewise_construct, forward_as_tuple(fd),
|
||||||
forward_as_tuple(this, name, fd, version, behavior));
|
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,
|
void connect_client(struct bufferevent* bev, uint32_t address, uint16_t port,
|
||||||
GameVersion version, ServerBehavior initial_state);
|
GameVersion version, ServerBehavior initial_state);
|
||||||
|
|
||||||
|
std::shared_ptr<Client> get_client() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PrefixedLogger log;
|
PrefixedLogger log;
|
||||||
std::shared_ptr<struct event_base> base;
|
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
|
// PROXY COMMANDS
|
||||||
|
|
||||||
} else if ((command_name == "sc") || (command_name == "ss")) {
|
} 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);
|
string data = parse_data_string(command_args);
|
||||||
if (data.size() & 3) {
|
if (data.size() & 3) {
|
||||||
throw invalid_argument("data size is not a multiple of 4");
|
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");
|
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")) {
|
} else if ((command_name == "chat") || (command_name == "dchat")) {
|
||||||
auto session = this->get_proxy_session();
|
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 ProxyServer;
|
||||||
|
class Server;
|
||||||
|
|
||||||
struct PortConfiguration {
|
struct PortConfiguration {
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -76,9 +77,8 @@ struct ServerState {
|
|||||||
uint32_t local_address;
|
uint32_t local_address;
|
||||||
uint32_t external_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<ProxyServer> proxy_server;
|
||||||
|
std::shared_ptr<Server> game_server;
|
||||||
|
|
||||||
ServerState();
|
ServerState();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user