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;
|
||||
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->listen("", state->dns_server_port);
|
||||
dns_server->listen(state->dns_server_addr, state->dns_server_port);
|
||||
} else {
|
||||
config_log.info("DNS server is disabled");
|
||||
}
|
||||
@@ -1934,14 +1938,14 @@ Action a_run_server_replay_log(
|
||||
auto [ss, size] = make_sockaddr_storage(
|
||||
state->proxy_destination_patch.first,
|
||||
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)) {
|
||||
auto [ss, size] = make_sockaddr_storage(
|
||||
state->proxy_destination_bb.first,
|
||||
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 {
|
||||
state->proxy_server->listen(pc->port, pc->version);
|
||||
state->proxy_server->listen(pc->addr, pc->port, pc->version);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1950,7 +1954,7 @@ Action a_run_server_replay_log(
|
||||
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));
|
||||
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),
|
||||
next_unlicensed_session_id(0xFF00000000000001) {}
|
||||
|
||||
void ProxyServer::listen(uint16_t port, Version version, const struct sockaddr_storage* default_destination) {
|
||||
auto socket_obj = make_shared<ListeningSocket>(this, port, version, default_destination);
|
||||
auto l = this->listeners.emplace(port, socket_obj).first->second;
|
||||
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, addr, port, version, default_destination);
|
||||
if (!this->listeners.emplace(port, socket_obj).second) {
|
||||
throw runtime_error("duplicate port in proxy server configuration");
|
||||
}
|
||||
}
|
||||
|
||||
ProxyServer::ListeningSocket::ListeningSocket(
|
||||
ProxyServer* server,
|
||||
const std::string& addr,
|
||||
uint16_t port,
|
||||
Version version,
|
||||
const struct sockaddr_storage* default_destination)
|
||||
: server(server),
|
||||
log(string_printf("[ProxyServer:ListeningSocket:%hu] ", port), proxy_server_log.min_level),
|
||||
port(port),
|
||||
fd(::listen("", port, SOMAXCONN)),
|
||||
fd(::listen(addr, port, SOMAXCONN)),
|
||||
listener(nullptr, evconnlistener_free),
|
||||
version(version) {
|
||||
if (!this->fd.is_open()) {
|
||||
|
||||
+2
-1
@@ -26,7 +26,7 @@ public:
|
||||
std::shared_ptr<ServerState> state);
|
||||
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);
|
||||
|
||||
@@ -207,6 +207,7 @@ private:
|
||||
|
||||
ListeningSocket(
|
||||
ProxyServer* server,
|
||||
const std::string& addr,
|
||||
uint16_t port,
|
||||
Version version,
|
||||
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;
|
||||
for (const auto& item_json_it : json.as_dict()) {
|
||||
const auto& item_list = item_json_it.second;
|
||||
PortConfiguration& pc = ret.emplace_back();
|
||||
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.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->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 {
|
||||
for (const auto& item : json.at("IPStackListen").as_list()) {
|
||||
if (item->is_int()) {
|
||||
|
||||
@@ -35,6 +35,7 @@ class Server;
|
||||
|
||||
struct PortConfiguration {
|
||||
std::string name;
|
||||
std::string addr; // Blank = listen on all interfaces (default)
|
||||
uint16_t port;
|
||||
Version version;
|
||||
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<uint16_t, std::shared_ptr<PortConfiguration>> number_to_port_config;
|
||||
std::string username;
|
||||
std::string dns_server_addr;
|
||||
uint16_t dns_server_port = 0;
|
||||
std::vector<std::string> ip_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& 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_default_lobbies();
|
||||
void collect_network_addresses();
|
||||
|
||||
@@ -37,7 +37,9 @@
|
||||
"ExternalAddress": "10.0.1.5",
|
||||
|
||||
// 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,
|
||||
|
||||
// Ports to listen for game connections on.
|
||||
@@ -45,6 +47,12 @@
|
||||
// Format of entries in this dictionary:
|
||||
// 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
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user