Add support for ipv6 addresses to addon client and multiplayer client
ipv6 address must be specifid surrounded by [], like [ipv6_address]:port, since otherwise impossible to disambiguate colons separating ipv6 quads from the colon delimiting port
This commit is contained in:
parent
7114174789
commit
34e2ef12c7
6 changed files with 77 additions and 27 deletions
|
@ -98,6 +98,7 @@
|
|||
as well.
|
||||
* Re-added the Font Scaling preference.
|
||||
* Enabled wesnothd and campaignd to accept IPv6 connections too
|
||||
* Added support for directly supplying IPv6 address of the server to multiplayer client and addon client. It must be done like this: ```[ipv6_address]``` or ```[ipv6_address]:port```
|
||||
|
||||
## Version 1.14.5+dev
|
||||
### AI
|
||||
|
|
|
@ -367,6 +367,7 @@ utils/context_free_grammar_generator.cpp
|
|||
utils/irdya_datetime.cpp
|
||||
utils/markov_generator.cpp
|
||||
utils/name_generator_factory.cpp
|
||||
utils/parse_network_address.cpp
|
||||
variable.cpp
|
||||
variable_info.cpp
|
||||
wesnothd_connection.cpp
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "serialization/parser.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
#include "serialization/utf8_exception.hpp"
|
||||
#include "utils/parse_network_address.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
|
@ -50,17 +51,11 @@ addons_client::addons_client(const std::string& address)
|
|||
, last_error_()
|
||||
, last_error_data_()
|
||||
{
|
||||
const std::vector<std::string>& address_components =
|
||||
utils::split(addr_, ':');
|
||||
|
||||
if(address_components.empty()) {
|
||||
try {
|
||||
std::tie(host_, port_) = parse_network_address(addr_, std::to_string(default_campaignd_port));
|
||||
} catch(const std::runtime_error&) {
|
||||
throw invalid_server_address();
|
||||
}
|
||||
|
||||
// FIXME: this parsing will break IPv6 numeric addresses! */
|
||||
host_ = address_components[0];
|
||||
port_ = address_components.size() == 2 ?
|
||||
address_components[1] : std::to_string(default_campaignd_port);
|
||||
}
|
||||
|
||||
void addons_client::connect()
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "map_settings.hpp"
|
||||
#include "sound.hpp"
|
||||
#include "statistics.hpp"
|
||||
#include "utils/parse_network_address.hpp"
|
||||
#include "wesnothd_connection.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "replay.hpp"
|
||||
|
@ -59,24 +60,20 @@ std::pair<wesnothd_connection_ptr, config> open_connection(std::string host)
|
|||
return std::make_pair(std::move(sock), config());
|
||||
}
|
||||
|
||||
const int colon_index = host.find_first_of(":");
|
||||
unsigned int port;
|
||||
|
||||
if(colon_index == -1) {
|
||||
port = 15000;
|
||||
} else {
|
||||
port = lexical_cast_default<unsigned int>(host.substr(colon_index + 1), 15000);
|
||||
host = host.substr(0, colon_index);
|
||||
}
|
||||
|
||||
// shown_hosts is used to prevent the client being locked in a redirect loop.
|
||||
using hostpair = std::pair<std::string, int>;
|
||||
using hostpair = std::pair<std::string, std::string>;
|
||||
|
||||
std::set<hostpair> shown_hosts;
|
||||
shown_hosts.emplace(host, port);
|
||||
hostpair addr;
|
||||
try {
|
||||
addr = parse_network_address(host, "15000");
|
||||
} catch(const std::runtime_error&) {
|
||||
throw wesnothd_error(_("Invalid address specified for multiplayer server"));
|
||||
}
|
||||
shown_hosts.insert(addr);
|
||||
|
||||
// Initializes the connection to the server.
|
||||
sock = std::make_unique<wesnothd_connection>(host, std::to_string(port));
|
||||
sock = std::make_unique<wesnothd_connection>(addr.first, addr.second);
|
||||
if(!sock) {
|
||||
return std::make_pair(std::move(sock), config());
|
||||
}
|
||||
|
@ -127,20 +124,20 @@ std::pair<wesnothd_connection_ptr, config> open_connection(std::string host)
|
|||
|
||||
// Check for "redirect" messages
|
||||
if(const config& redirect = data.child("redirect")) {
|
||||
host = redirect["host"].str();
|
||||
port = redirect["port"].to_int(15000);
|
||||
auto redirect_host = redirect["host"].str();
|
||||
auto redirect_port = redirect["port"].str("15000");
|
||||
|
||||
if(shown_hosts.find(hostpair(host, port)) != shown_hosts.end()) {
|
||||
if(shown_hosts.find(hostpair(redirect_host, redirect_port)) != shown_hosts.end()) {
|
||||
throw wesnothd_error(_("Server-side redirect loop"));
|
||||
}
|
||||
|
||||
shown_hosts.emplace(host, port);
|
||||
shown_hosts.emplace(redirect_host, redirect_port);
|
||||
|
||||
gui2::dialogs::loading_screen::progress(loading_stage::redirect);
|
||||
|
||||
// Open a new connection with the new host and port.
|
||||
sock.reset();
|
||||
sock = std::make_unique<wesnothd_connection>(host, std::to_string(port));
|
||||
sock = std::make_unique<wesnothd_connection>(redirect_host, redirect_port);
|
||||
|
||||
// Wait for new handshake.
|
||||
while(!sock->handshake_finished()) {
|
||||
|
|
32
src/utils/parse_network_address.cpp
Normal file
32
src/utils/parse_network_address.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright (C) 2019 by Sergey Popov <loonycyborg@gmail.com>
|
||||
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
std::pair<std::string, std::string> parse_network_address(const std::string& address, const std::string& default_port)
|
||||
{
|
||||
const char* address_re = "\\[([[:xdigit:]:]*)\\](:(.*))?|([^:]*)(:([[:alnum:]]*))?";
|
||||
|
||||
std::smatch m;
|
||||
std::regex_match(address, m, std::regex(address_re));
|
||||
|
||||
if(!m[1].str().empty()) {
|
||||
return { m[1], m[3].str().empty() ? default_port : m[3] };
|
||||
}
|
||||
if(!m[4].str().empty()) {
|
||||
return { m[4], m[6].str().empty() ? default_port : m[6] };
|
||||
}
|
||||
|
||||
throw std::runtime_error("invalid address");
|
||||
}
|
24
src/utils/parse_network_address.hpp
Normal file
24
src/utils/parse_network_address.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright (C) 2019 by Sergey Popov <loonycyborg@gmail.com>
|
||||
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Parse a host:port style network address, supporting [] notation for ipv6 addresses
|
||||
* @param address
|
||||
* @param default_port the port to return if address doesn't have it specified
|
||||
*/
|
||||
std::pair<std::string, std::string> parse_network_address(const std::string& address, const std::string& default_port);
|
||||
|
Loading…
Add table
Reference in a new issue