Merge branch 'master' into jgrpp-beta

# Conflicts:
#	src/console_cmds.cpp
#	src/debug.cpp
#	src/lang/vietnamese.txt
#	src/network/core/address.cpp
#	src/network/core/address.h
#	src/network/core/config.h
#	src/network/core/os_abstraction.cpp
#	src/network/core/os_abstraction.h
#	src/network/core/tcp_listen.h
#	src/network/core/udp.cpp
#	src/network/core/udp.h
#	src/network/network.cpp
#	src/network/network_client.cpp
#	src/network/network_gamelist.cpp
#	src/network/network_server.cpp
#	src/network/network_udp.cpp
#	src/newgrf.cpp
#	src/openttd.cpp
#	src/saveload/saveload.h
#	src/settings.cpp
#	src/settings_table.cpp
#	src/settings_type.h
#	src/table/settings/network_settings.ini
This commit is contained in:
Jonathan G Rennison
2021-11-02 00:51:54 +00:00
124 changed files with 3050 additions and 1274 deletions

View File

@@ -13,6 +13,7 @@
#include "../../thread.h"
#include "tcp.h"
#include "../network_coordinator.h"
#include "../network_internal.h"
#include <deque>
@@ -23,16 +24,45 @@
static std::vector<TCPConnecter *> _tcp_connecters;
/**
* Create a new connecter for the given address
* @param connection_string the address to connect to
* Create a new connecter for the given address.
* @param connection_string The address to connect to.
* @param default_port If not indicated in connection_string, what port to use.
* @param bind_address The local bind address to use. Defaults to letting the OS find one.
*/
TCPConnecter::TCPConnecter(const std::string &connection_string, uint16 default_port)
TCPConnecter::TCPConnecter(const std::string &connection_string, uint16 default_port, NetworkAddress bind_address, int family) :
bind_address(bind_address),
family(family)
{
this->connection_string = NormalizeConnectionString(connection_string, default_port);
_tcp_connecters.push_back(this);
}
/**
* Create a new connecter for the server.
* @param connection_string The address to connect to.
* @param default_port If not indicated in connection_string, what port to use.
*/
TCPServerConnecter::TCPServerConnecter(const std::string &connection_string, uint16 default_port) :
server_address(ServerAddress::Parse(connection_string, default_port))
{
switch (this->server_address.type) {
case SERVER_ADDRESS_DIRECT:
this->connection_string = this->server_address.connection_string;
break;
case SERVER_ADDRESS_INVITE_CODE:
this->status = Status::CONNECTING;
_network_coordinator_client.ConnectToServer(this->server_address.connection_string, this);
break;
default:
NOT_REACHED();
}
_tcp_connecters.push_back(this);
}
TCPConnecter::~TCPConnecter()
{
if (this->resolve_thread.joinable()) {
@@ -48,6 +78,16 @@ TCPConnecter::~TCPConnecter()
if (this->ai != nullptr) freeaddrinfo(this->ai);
}
/**
* Kill this connecter.
* It will abort as soon as it can and not call any of the callbacks.
*/
void TCPConnecter::Kill()
{
/* Delay the removing of the socket till the next CheckActivity(). */
this->killed = true;
}
/**
* Start a connection to the indicated address.
* @param address The address to connection to.
@@ -60,6 +100,18 @@ void TCPConnecter::Connect(addrinfo *address)
return;
}
if (!SetReusePort(sock)) {
DEBUG(net, 0, "Setting reuse-port mode failed: %s", NetworkError::GetLast().AsString());
}
if (this->bind_address.GetPort() > 0) {
if (bind(sock, (const sockaddr *)this->bind_address.GetAddress(), this->bind_address.GetAddressLength()) != 0) {
DEBUG(net, 1, "Could not bind socket on %s: %s", NetworkAddressDumper().GetAddressAsString(&(this->bind_address)), NetworkError::GetLast().AsString());
closesocket(sock);
return;
}
}
if (!SetNoDelay(sock)) {
DEBUG(net, 1, "Setting TCP_NODELAY failed: %s", NetworkError::GetLast().AsString());
}
@@ -123,6 +175,9 @@ void TCPConnecter::OnResolved(addrinfo *ai)
/* Convert the addrinfo into NetworkAddresses. */
for (addrinfo *runp = ai; runp != nullptr; runp = runp->ai_next) {
/* Skip entries if the family is set and it is not matching. */
if (this->family != AF_UNSPEC && this->family != runp->ai_family) continue;
if (resort) {
if (runp->ai_family == AF_INET6) {
addresses_ipv6.emplace_back(runp);
@@ -219,7 +274,9 @@ void TCPConnecter::Resolve()
*/
bool TCPConnecter::CheckActivity()
{
switch (this->status.load()) {
if (this->killed) return true;
switch (this->status) {
case Status::INIT:
/* Start the thread delayed, so the vtable is loaded. This allows classes
* to overload functions used by Resolve() (in case threading is disabled). */
@@ -246,6 +303,7 @@ bool TCPConnecter::CheckActivity()
return true;
case Status::CONNECTING:
case Status::CONNECTED:
break;
}
@@ -344,9 +402,63 @@ bool TCPConnecter::CheckActivity()
}
this->OnConnect(connected_socket);
this->status = Status::CONNECTED;
return true;
}
/**
* Check if there was activity for this connecter.
* @return True iff the TCPConnecter is done and can be cleaned up.
*/
bool TCPServerConnecter::CheckActivity()
{
if (this->killed) return true;
switch (this->server_address.type) {
case SERVER_ADDRESS_DIRECT:
return TCPConnecter::CheckActivity();
case SERVER_ADDRESS_INVITE_CODE:
/* Check if a result has come in. */
switch (this->status) {
case Status::FAILURE:
this->OnFailure();
return true;
case Status::CONNECTED:
this->OnConnect(this->socket);
return true;
default:
break;
}
return false;
default:
NOT_REACHED();
}
}
/**
* The connection was successfully established.
* This socket is fully setup and ready to send/recv game protocol packets.
* @param sock The socket of the established connection.
*/
void TCPServerConnecter::SetConnected(SOCKET sock)
{
this->socket = sock;
this->status = Status::CONNECTED;
}
/**
* The connection couldn't be established.
*/
void TCPServerConnecter::SetFailure()
{
this->status = Status::FAILURE;
}
/**
* Check whether we need to call the callback, i.e. whether we
* have connected or aborted and call the appropriate callback