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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user