add ability to specify listening interfaces
This commit is contained in:
+10
-6
@@ -1890,9 +1890,13 @@ Action a_run_server_replay_log(
|
|||||||
|
|
||||||
shared_ptr<DNSServer> dns_server;
|
shared_ptr<DNSServer> dns_server;
|
||||||
if (state->dns_server_port && !is_replay) {
|
if (state->dns_server_port && !is_replay) {
|
||||||
config_log.info("Starting DNS server on port %hu", state->dns_server_port);
|
if (!state->dns_server_addr.empty()) {
|
||||||
|
config_log.info("Starting DNS server on %s:%hu", state->dns_server_addr.c_str(), state->dns_server_port);
|
||||||
|
} else {
|
||||||
|
config_log.info("Starting DNS server on port %hu", state->dns_server_port);
|
||||||
|
}
|
||||||
dns_server = make_shared<DNSServer>(base, state->local_address, state->external_address);
|
dns_server = make_shared<DNSServer>(base, state->local_address, state->external_address);
|
||||||
dns_server->listen("", state->dns_server_port);
|
dns_server->listen(state->dns_server_addr, state->dns_server_port);
|
||||||
} else {
|
} else {
|
||||||
config_log.info("DNS server is disabled");
|
config_log.info("DNS server is disabled");
|
||||||
}
|
}
|
||||||
@@ -1934,14 +1938,14 @@ Action a_run_server_replay_log(
|
|||||||
auto [ss, size] = make_sockaddr_storage(
|
auto [ss, size] = make_sockaddr_storage(
|
||||||
state->proxy_destination_patch.first,
|
state->proxy_destination_patch.first,
|
||||||
state->proxy_destination_patch.second);
|
state->proxy_destination_patch.second);
|
||||||
state->proxy_server->listen(pc->port, pc->version, &ss);
|
state->proxy_server->listen(pc->addr, pc->port, pc->version, &ss);
|
||||||
} else if (is_v4(pc->version)) {
|
} else if (is_v4(pc->version)) {
|
||||||
auto [ss, size] = make_sockaddr_storage(
|
auto [ss, size] = make_sockaddr_storage(
|
||||||
state->proxy_destination_bb.first,
|
state->proxy_destination_bb.first,
|
||||||
state->proxy_destination_bb.second);
|
state->proxy_destination_bb.second);
|
||||||
state->proxy_server->listen(pc->port, pc->version, &ss);
|
state->proxy_server->listen(pc->addr, pc->port, pc->version, &ss);
|
||||||
} else {
|
} else {
|
||||||
state->proxy_server->listen(pc->port, pc->version);
|
state->proxy_server->listen(pc->addr, pc->port, pc->version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1950,7 +1954,7 @@ Action a_run_server_replay_log(
|
|||||||
state->game_server = make_shared<Server>(base, state);
|
state->game_server = make_shared<Server>(base, state);
|
||||||
}
|
}
|
||||||
string spec = string_printf("T-%hu-%s-%s-%s", pc->port, name_for_enum(pc->version), pc->name.c_str(), name_for_enum(pc->behavior));
|
string spec = string_printf("T-%hu-%s-%s-%s", pc->port, name_for_enum(pc->version), pc->name.c_str(), name_for_enum(pc->behavior));
|
||||||
state->game_server->listen(spec, "", pc->port, pc->version, pc->behavior);
|
state->game_server->listen(spec, pc->addr, pc->port, pc->version, pc->behavior);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-4
@@ -43,20 +43,23 @@ ProxyServer::ProxyServer(
|
|||||||
state(state),
|
state(state),
|
||||||
next_unlicensed_session_id(0xFF00000000000001) {}
|
next_unlicensed_session_id(0xFF00000000000001) {}
|
||||||
|
|
||||||
void ProxyServer::listen(uint16_t port, Version version, const struct sockaddr_storage* default_destination) {
|
void ProxyServer::listen(const std::string& addr, uint16_t port, Version version, const struct sockaddr_storage* default_destination) {
|
||||||
auto socket_obj = make_shared<ListeningSocket>(this, port, version, default_destination);
|
auto socket_obj = make_shared<ListeningSocket>(this, addr, port, version, default_destination);
|
||||||
auto l = this->listeners.emplace(port, socket_obj).first->second;
|
if (!this->listeners.emplace(port, socket_obj).second) {
|
||||||
|
throw runtime_error("duplicate port in proxy server configuration");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxyServer::ListeningSocket::ListeningSocket(
|
ProxyServer::ListeningSocket::ListeningSocket(
|
||||||
ProxyServer* server,
|
ProxyServer* server,
|
||||||
|
const std::string& addr,
|
||||||
uint16_t port,
|
uint16_t port,
|
||||||
Version version,
|
Version version,
|
||||||
const struct sockaddr_storage* default_destination)
|
const struct sockaddr_storage* default_destination)
|
||||||
: server(server),
|
: server(server),
|
||||||
log(string_printf("[ProxyServer:ListeningSocket:%hu] ", port), proxy_server_log.min_level),
|
log(string_printf("[ProxyServer:ListeningSocket:%hu] ", port), proxy_server_log.min_level),
|
||||||
port(port),
|
port(port),
|
||||||
fd(::listen("", port, SOMAXCONN)),
|
fd(::listen(addr, port, SOMAXCONN)),
|
||||||
listener(nullptr, evconnlistener_free),
|
listener(nullptr, evconnlistener_free),
|
||||||
version(version) {
|
version(version) {
|
||||||
if (!this->fd.is_open()) {
|
if (!this->fd.is_open()) {
|
||||||
|
|||||||
+2
-1
@@ -26,7 +26,7 @@ public:
|
|||||||
std::shared_ptr<ServerState> state);
|
std::shared_ptr<ServerState> state);
|
||||||
virtual ~ProxyServer() = default;
|
virtual ~ProxyServer() = default;
|
||||||
|
|
||||||
void listen(uint16_t port, Version version, const struct sockaddr_storage* default_destination = nullptr);
|
void listen(const std::string& addr, uint16_t port, Version version, const struct sockaddr_storage* default_destination = nullptr);
|
||||||
|
|
||||||
void connect_client(struct bufferevent* bev, uint16_t server_port);
|
void connect_client(struct bufferevent* bev, uint16_t server_port);
|
||||||
|
|
||||||
@@ -207,6 +207,7 @@ private:
|
|||||||
|
|
||||||
ListeningSocket(
|
ListeningSocket(
|
||||||
ProxyServer* server,
|
ProxyServer* server,
|
||||||
|
const std::string& addr,
|
||||||
uint16_t port,
|
uint16_t port,
|
||||||
Version version,
|
Version version,
|
||||||
const struct sockaddr_storage* default_destination);
|
const struct sockaddr_storage* default_destination);
|
||||||
|
|||||||
+23
-3
@@ -472,13 +472,28 @@ shared_ptr<const string> ServerState::load_bb_file(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static vector<PortConfiguration> parse_port_configuration(const JSON& json) {
|
pair<string, uint16_t> ServerState::parse_port_spec(const JSON& json) const {
|
||||||
|
if (json.is_list()) {
|
||||||
|
string addr = json.at(0).as_string();
|
||||||
|
try {
|
||||||
|
addr = string_for_address(this->all_addresses.at(addr));
|
||||||
|
} catch (const out_of_range&) {
|
||||||
|
}
|
||||||
|
return make_pair(addr, json.at(1).as_int());
|
||||||
|
} else {
|
||||||
|
return make_pair("", json.as_int());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<PortConfiguration> ServerState::parse_port_configuration(const JSON& json) const {
|
||||||
vector<PortConfiguration> ret;
|
vector<PortConfiguration> ret;
|
||||||
for (const auto& item_json_it : json.as_dict()) {
|
for (const auto& item_json_it : json.as_dict()) {
|
||||||
const auto& item_list = item_json_it.second;
|
const auto& item_list = item_json_it.second;
|
||||||
PortConfiguration& pc = ret.emplace_back();
|
PortConfiguration& pc = ret.emplace_back();
|
||||||
pc.name = item_json_it.first;
|
pc.name = item_json_it.first;
|
||||||
pc.port = item_list->at(0).as_int();
|
auto spec = this->parse_port_spec(item_list->at(0));
|
||||||
|
pc.addr = std::move(spec.first);
|
||||||
|
pc.port = spec.second;
|
||||||
pc.version = enum_for_name<Version>(item_list->at(1).as_string().c_str());
|
pc.version = enum_for_name<Version>(item_list->at(1).as_string().c_str());
|
||||||
pc.behavior = enum_for_name<ServerBehavior>(item_list->at(2).as_string().c_str());
|
pc.behavior = enum_for_name<ServerBehavior>(item_list->at(2).as_string().c_str());
|
||||||
}
|
}
|
||||||
@@ -537,7 +552,12 @@ void ServerState::load_config() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->set_port_configuration(parse_port_configuration(json.at("PortConfiguration")));
|
this->set_port_configuration(parse_port_configuration(json.at("PortConfiguration")));
|
||||||
this->dns_server_port = json.get_int("DNSServerPort", this->dns_server_port);
|
try {
|
||||||
|
auto spec = this->parse_port_spec(json.at("DNSServerPort"));
|
||||||
|
this->dns_server_addr = std::move(spec.first);
|
||||||
|
this->dns_server_port = spec.second;
|
||||||
|
} catch (const out_of_range&) {
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
for (const auto& item : json.at("IPStackListen").as_list()) {
|
for (const auto& item : json.at("IPStackListen").as_list()) {
|
||||||
if (item->is_int()) {
|
if (item->is_int()) {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class Server;
|
|||||||
|
|
||||||
struct PortConfiguration {
|
struct PortConfiguration {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
std::string addr; // Blank = listen on all interfaces (default)
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
Version version;
|
Version version;
|
||||||
ServerBehavior behavior;
|
ServerBehavior behavior;
|
||||||
@@ -74,6 +75,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
|||||||
std::unordered_map<std::string, std::shared_ptr<PortConfiguration>> name_to_port_config;
|
std::unordered_map<std::string, std::shared_ptr<PortConfiguration>> name_to_port_config;
|
||||||
std::unordered_map<uint16_t, std::shared_ptr<PortConfiguration>> number_to_port_config;
|
std::unordered_map<uint16_t, std::shared_ptr<PortConfiguration>> number_to_port_config;
|
||||||
std::string username;
|
std::string username;
|
||||||
|
std::string dns_server_addr;
|
||||||
uint16_t dns_server_port = 0;
|
uint16_t dns_server_port = 0;
|
||||||
std::vector<std::string> ip_stack_addresses;
|
std::vector<std::string> ip_stack_addresses;
|
||||||
std::vector<std::string> ppp_stack_addresses;
|
std::vector<std::string> ppp_stack_addresses;
|
||||||
@@ -283,6 +285,9 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
|||||||
const std::string& gsl_filename = "",
|
const std::string& gsl_filename = "",
|
||||||
const std::string& bb_directory_filename = "") const;
|
const std::string& bb_directory_filename = "") const;
|
||||||
|
|
||||||
|
std::pair<std::string, uint16_t> parse_port_spec(const JSON& json) const;
|
||||||
|
std::vector<PortConfiguration> parse_port_configuration(const JSON& json) const;
|
||||||
|
|
||||||
void create_load_step_graph();
|
void create_load_step_graph();
|
||||||
void create_default_lobbies();
|
void create_default_lobbies();
|
||||||
void collect_network_addresses();
|
void collect_network_addresses();
|
||||||
|
|||||||
@@ -37,7 +37,9 @@
|
|||||||
"ExternalAddress": "10.0.1.5",
|
"ExternalAddress": "10.0.1.5",
|
||||||
|
|
||||||
// Port to listen for DNS queries on. To disable the DNS server, comment this
|
// Port to listen for DNS queries on. To disable the DNS server, comment this
|
||||||
// out or set it to zero.
|
// out or set it to zero. By default, the DNS server listens on all
|
||||||
|
// interfaces, but you can specify an interface by replacing this with a list
|
||||||
|
// of [interface_addr_or_name, port].
|
||||||
"DNSServerPort": 53,
|
"DNSServerPort": 53,
|
||||||
|
|
||||||
// Ports to listen for game connections on.
|
// Ports to listen for game connections on.
|
||||||
@@ -45,6 +47,12 @@
|
|||||||
// Format of entries in this dictionary:
|
// Format of entries in this dictionary:
|
||||||
// name: [port, version, behavior]
|
// name: [port, version, behavior]
|
||||||
|
|
||||||
|
// port is normally just an integer (which will cause the server to listen
|
||||||
|
// on that port on all interfaces), but you can also replace the integer
|
||||||
|
// with a 2-list of [address, port] to listen in a specific port. For
|
||||||
|
// example, that might look like:
|
||||||
|
// "xb-login": [["en0", 9500], "xb", "login_server"],
|
||||||
|
|
||||||
// Various versions of PSO hardcode these ports in the clients. Don't change
|
// Various versions of PSO hardcode these ports in the clients. Don't change
|
||||||
// these unless you don't want to support certain versions of PSO.
|
// these unless you don't want to support certain versions of PSO.
|
||||||
// Note: The pc_console_detect behavior is used for separating PSO PC and
|
// Note: The pc_console_detect behavior is used for separating PSO PC and
|
||||||
|
|||||||
Reference in New Issue
Block a user