mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 14:27:16 +00:00
Change: use TCP for everything except for master-server and initial server scan (#9130)
This means that pressing Refresh button and adding servers manually now uses TCP. The master-server and initial scan are still UDP as they will be replaced by Game Coordinator; no need to change this now. If we query a server that is too old, show a proper warning to the user informing him the server is too old.
This commit is contained in:
parent
f00564eeb2
commit
69118d063f
@ -65,10 +65,14 @@ Module.preRun.push(function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.openttd_server_list = function() {
|
window.openttd_server_list = function() {
|
||||||
add_server = Module.cwrap("em_openttd_add_server", null, ["string", "number"]);
|
add_server = Module.cwrap("em_openttd_add_server", null, ["string"]);
|
||||||
|
|
||||||
/* Add servers that support WebSocket here. Example:
|
/* Add servers that support WebSocket here. Examples:
|
||||||
* add_server("localhost", 3979); */
|
* add_server("localhost");
|
||||||
|
* add_server("localhost:3979");
|
||||||
|
* add_server("127.0.0.1:3979");
|
||||||
|
* add_server("[::1]:3979");
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
var leftButtonDown = false;
|
var leftButtonDown = false;
|
||||||
|
@ -2217,6 +2217,7 @@ STR_NETWORK_ERROR_TIMEOUT_COMPUTER :{WHITE}Your com
|
|||||||
STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Your computer took too long to download the map
|
STR_NETWORK_ERROR_TIMEOUT_MAP :{WHITE}Your computer took too long to download the map
|
||||||
STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Your computer took too long to join the server
|
STR_NETWORK_ERROR_TIMEOUT_JOIN :{WHITE}Your computer took too long to join the server
|
||||||
STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Your player name is not valid
|
STR_NETWORK_ERROR_INVALID_CLIENT_NAME :{WHITE}Your player name is not valid
|
||||||
|
STR_NETWORK_ERROR_SERVER_TOO_OLD :{WHITE}The queried server is too old for this client
|
||||||
|
|
||||||
############ Leave those lines in this order!!
|
############ Leave those lines in this order!!
|
||||||
STR_NETWORK_ERROR_CLIENT_GENERAL :general error
|
STR_NETWORK_ERROR_CLIENT_GENERAL :general error
|
||||||
|
@ -602,8 +602,11 @@ static void NetworkInitialize(bool close_admins = true)
|
|||||||
|
|
||||||
/** Non blocking connection create to query servers */
|
/** Non blocking connection create to query servers */
|
||||||
class TCPQueryConnecter : TCPConnecter {
|
class TCPQueryConnecter : TCPConnecter {
|
||||||
|
private:
|
||||||
|
bool request_company_info;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TCPQueryConnecter(const NetworkAddress &address) : TCPConnecter(address) {}
|
TCPQueryConnecter(const NetworkAddress &address, bool request_company_info) : TCPConnecter(address), request_company_info(request_company_info) {}
|
||||||
|
|
||||||
void OnFailure() override
|
void OnFailure() override
|
||||||
{
|
{
|
||||||
@ -613,36 +616,53 @@ public:
|
|||||||
void OnConnect(SOCKET s) override
|
void OnConnect(SOCKET s) override
|
||||||
{
|
{
|
||||||
_networking = true;
|
_networking = true;
|
||||||
new ClientNetworkGameSocketHandler(s);
|
new ClientNetworkGameSocketHandler(s, address);
|
||||||
MyClient::SendInformationQuery();
|
MyClient::SendInformationQuery(request_company_info);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query a server to fetch his game-info.
|
* Query a server to fetch his game-info.
|
||||||
* @param address the address to query.
|
* @param address the address to query.
|
||||||
|
* @param request_company_info Whether to request company info too.
|
||||||
*/
|
*/
|
||||||
void NetworkTCPQueryServer(NetworkAddress address)
|
void NetworkTCPQueryServer(NetworkAddress address, bool request_company_info)
|
||||||
{
|
{
|
||||||
if (!_network_available) return;
|
if (!_network_available) return;
|
||||||
|
|
||||||
NetworkDisconnect();
|
NetworkDisconnect();
|
||||||
NetworkInitialize();
|
NetworkInitialize();
|
||||||
|
|
||||||
new TCPQueryConnecter(address);
|
new TCPQueryConnecter(address, request_company_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates an address entered as a string and adds the server to
|
* Validates an address entered as a string and adds the server to
|
||||||
* the list. If you use this function, the games will be marked
|
* the list. If you use this function, the games will be marked
|
||||||
* as manually added.
|
* as manually added.
|
||||||
* @param connection_string The IP:port to add to the list.
|
* @param connection_string The IP:port of the server to add.
|
||||||
|
* @return The entry on the game list.
|
||||||
*/
|
*/
|
||||||
void NetworkAddServer(const char *connection_string)
|
NetworkGameList *NetworkAddServer(const std::string &connection_string)
|
||||||
{
|
{
|
||||||
if (StrEmpty(connection_string)) return;
|
if (connection_string.empty()) return nullptr;
|
||||||
|
|
||||||
NetworkUDPQueryServer(ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT), true);
|
NetworkAddress address = ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT);
|
||||||
|
|
||||||
|
/* Ensure the item already exists in the list */
|
||||||
|
NetworkGameList *item = NetworkGameListAddItem(address);
|
||||||
|
if (StrEmpty(item->info.server_name)) {
|
||||||
|
ClearGRFConfigList(&item->info.grfconfig);
|
||||||
|
address.GetAddressAsString(item->info.server_name, lastof(item->info.server_name));
|
||||||
|
item->manually = true;
|
||||||
|
|
||||||
|
NetworkRebuildHostList();
|
||||||
|
UpdateNetworkGameWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkTCPQueryServer(address);
|
||||||
|
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -687,7 +707,7 @@ public:
|
|||||||
void OnConnect(SOCKET s) override
|
void OnConnect(SOCKET s) override
|
||||||
{
|
{
|
||||||
_networking = true;
|
_networking = true;
|
||||||
new ClientNetworkGameSocketHandler(s);
|
new ClientNetworkGameSocketHandler(s, this->address);
|
||||||
IConsoleCmdExec("exec scripts/on_client.scr 0");
|
IConsoleCmdExec("exec scripts/on_client.scr 0");
|
||||||
NetworkClient_Connected();
|
NetworkClient_Connected();
|
||||||
}
|
}
|
||||||
@ -1132,9 +1152,9 @@ void NetworkShutDown()
|
|||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
void CDECL em_openttd_add_server(const char *host, int port)
|
void CDECL em_openttd_add_server(const char *connection_string)
|
||||||
{
|
{
|
||||||
NetworkUDPQueryServer(NetworkAddress(host, port), true);
|
NetworkAddServer(connection_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ void ClientNetworkEmergencySave()
|
|||||||
* Create a new socket for the client side of the game connection.
|
* Create a new socket for the client side of the game connection.
|
||||||
* @param s The socket to connect with.
|
* @param s The socket to connect with.
|
||||||
*/
|
*/
|
||||||
ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s) : NetworkGameSocketHandler(s), savegame(nullptr), status(STATUS_INACTIVE)
|
ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s, NetworkAddress address) : NetworkGameSocketHandler(s), address(address), savegame(nullptr), status(STATUS_INACTIVE)
|
||||||
{
|
{
|
||||||
assert(ClientNetworkGameSocketHandler::my_client == nullptr);
|
assert(ClientNetworkGameSocketHandler::my_client == nullptr);
|
||||||
ClientNetworkGameSocketHandler::my_client = this;
|
ClientNetworkGameSocketHandler::my_client = this;
|
||||||
@ -345,14 +345,18 @@ static_assert(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1);
|
|||||||
/**
|
/**
|
||||||
* Query the server for server information.
|
* Query the server for server information.
|
||||||
*/
|
*/
|
||||||
NetworkRecvStatus ClientNetworkGameSocketHandler::SendInformationQuery()
|
NetworkRecvStatus ClientNetworkGameSocketHandler::SendInformationQuery(bool request_company_info)
|
||||||
{
|
{
|
||||||
|
my_client->status = STATUS_GAME_INFO;
|
||||||
|
my_client->SendPacket(new Packet(PACKET_CLIENT_GAME_INFO));
|
||||||
|
|
||||||
|
if (request_company_info) {
|
||||||
my_client->status = STATUS_COMPANY_INFO;
|
my_client->status = STATUS_COMPANY_INFO;
|
||||||
_network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
|
_network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
|
||||||
SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
|
SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
|
||||||
|
|
||||||
my_client->SendPacket(new Packet(PACKET_CLIENT_GAME_INFO));
|
|
||||||
my_client->SendPacket(new Packet(PACKET_CLIENT_COMPANY_INFO));
|
my_client->SendPacket(new Packet(PACKET_CLIENT_COMPANY_INFO));
|
||||||
|
}
|
||||||
|
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
}
|
}
|
||||||
@ -577,9 +581,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet *
|
|||||||
|
|
||||||
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet *p)
|
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet *p)
|
||||||
{
|
{
|
||||||
if (this->status != STATUS_COMPANY_INFO && this->status != STATUS_INACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
if (this->status != STATUS_COMPANY_INFO && this->status != STATUS_GAME_INFO) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||||
|
|
||||||
NetworkGameList *item = GetLobbyGameInfo();
|
NetworkGameList *item = GetLobbyGameInfo();
|
||||||
|
if (item == nullptr) {
|
||||||
|
/* This is not the lobby, so add it to the game list. */
|
||||||
|
item = NetworkGameListAddItem(this->address);
|
||||||
|
}
|
||||||
|
|
||||||
/* Clear any existing GRFConfig chain. */
|
/* Clear any existing GRFConfig chain. */
|
||||||
ClearGRFConfigList(&item->info.grfconfig);
|
ClearGRFConfigList(&item->info.grfconfig);
|
||||||
@ -590,6 +598,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packe
|
|||||||
/* Ensure we consider the server online. */
|
/* Ensure we consider the server online. */
|
||||||
item->online = true;
|
item->online = true;
|
||||||
|
|
||||||
|
/* It could be either window, but only one is open, so redraw both. */
|
||||||
|
SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME);
|
||||||
SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);
|
SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY);
|
||||||
|
|
||||||
/* We will receive company info next, so keep connection open. */
|
/* We will receive company info next, so keep connection open. */
|
||||||
@ -727,6 +737,15 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p
|
|||||||
|
|
||||||
NetworkErrorCode error = (NetworkErrorCode)p->Recv_uint8();
|
NetworkErrorCode error = (NetworkErrorCode)p->Recv_uint8();
|
||||||
|
|
||||||
|
/* If we query a server that is 1.11.1 or older, we get an
|
||||||
|
* NETWORK_ERROR_NOT_EXPECTED on requesting the game info. Show a special
|
||||||
|
* error popup in that case.
|
||||||
|
*/
|
||||||
|
if (error == NETWORK_ERROR_NOT_EXPECTED && (this->status == STATUS_GAME_INFO || this->status == STATUS_COMPANY_INFO)) {
|
||||||
|
ShowErrorMessage(STR_NETWORK_ERROR_SERVER_TOO_OLD, INVALID_STRING_ID, WL_CRITICAL);
|
||||||
|
return NETWORK_RECV_STATUS_CLOSE_QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
StringID err = STR_NETWORK_ERROR_LOSTCONNECTION;
|
StringID err = STR_NETWORK_ERROR_LOSTCONNECTION;
|
||||||
if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error];
|
if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error];
|
||||||
/* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */
|
/* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */
|
||||||
|
@ -15,12 +15,14 @@
|
|||||||
/** Class for handling the client side of the game connection. */
|
/** Class for handling the client side of the game connection. */
|
||||||
class ClientNetworkGameSocketHandler : public ZeroedMemoryAllocator, public NetworkGameSocketHandler {
|
class ClientNetworkGameSocketHandler : public ZeroedMemoryAllocator, public NetworkGameSocketHandler {
|
||||||
private:
|
private:
|
||||||
|
NetworkAddress address; ///< Address we are connected to.
|
||||||
struct PacketReader *savegame; ///< Packet reader for reading the savegame.
|
struct PacketReader *savegame; ///< Packet reader for reading the savegame.
|
||||||
byte token; ///< The token we need to send back to the server to prove we're the right client.
|
byte token; ///< The token we need to send back to the server to prove we're the right client.
|
||||||
|
|
||||||
/** Status of the connection with the server. */
|
/** Status of the connection with the server. */
|
||||||
enum ServerStatus {
|
enum ServerStatus {
|
||||||
STATUS_INACTIVE, ///< The client is not connected nor active.
|
STATUS_INACTIVE, ///< The client is not connected nor active.
|
||||||
|
STATUS_GAME_INFO, ///< We are trying to get the game information.
|
||||||
STATUS_COMPANY_INFO, ///< We are trying to get company information.
|
STATUS_COMPANY_INFO, ///< We are trying to get company information.
|
||||||
STATUS_JOIN, ///< We are trying to join a server.
|
STATUS_JOIN, ///< We are trying to join a server.
|
||||||
STATUS_NEWGRFS_CHECK, ///< Last action was checking NewGRFs.
|
STATUS_NEWGRFS_CHECK, ///< Last action was checking NewGRFs.
|
||||||
@ -74,13 +76,13 @@ protected:
|
|||||||
static NetworkRecvStatus SendMapOk();
|
static NetworkRecvStatus SendMapOk();
|
||||||
void CheckConnection();
|
void CheckConnection();
|
||||||
public:
|
public:
|
||||||
ClientNetworkGameSocketHandler(SOCKET s);
|
ClientNetworkGameSocketHandler(SOCKET s, NetworkAddress address);
|
||||||
~ClientNetworkGameSocketHandler();
|
~ClientNetworkGameSocketHandler();
|
||||||
|
|
||||||
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override;
|
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override;
|
||||||
void ClientError(NetworkRecvStatus res);
|
void ClientError(NetworkRecvStatus res);
|
||||||
|
|
||||||
static NetworkRecvStatus SendInformationQuery();
|
static NetworkRecvStatus SendInformationQuery(bool request_company_info);
|
||||||
|
|
||||||
static NetworkRecvStatus SendJoin();
|
static NetworkRecvStatus SendJoin();
|
||||||
static NetworkRecvStatus SendCommand(const CommandPacket *cp);
|
static NetworkRecvStatus SendCommand(const CommandPacket *cp);
|
||||||
|
@ -69,15 +69,6 @@ static void NetworkGameListHandleDelayedInsert()
|
|||||||
*/
|
*/
|
||||||
NetworkGameList *NetworkGameListAddItem(NetworkAddress address)
|
NetworkGameList *NetworkGameListAddItem(NetworkAddress address)
|
||||||
{
|
{
|
||||||
const char *hostname = address.GetHostname();
|
|
||||||
|
|
||||||
/* Do not query the 'any' address. */
|
|
||||||
if (StrEmpty(hostname) ||
|
|
||||||
strcmp(hostname, "0.0.0.0") == 0 ||
|
|
||||||
strcmp(hostname, "::") == 0) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkGameList *item, *prev_item;
|
NetworkGameList *item, *prev_item;
|
||||||
|
|
||||||
prev_item = nullptr;
|
prev_item = nullptr;
|
||||||
@ -95,7 +86,6 @@ NetworkGameList *NetworkGameListAddItem(NetworkAddress address)
|
|||||||
} else {
|
} else {
|
||||||
prev_item->next = item;
|
prev_item->next = item;
|
||||||
}
|
}
|
||||||
DEBUG(net, 4, "[gamelist] added server to list");
|
|
||||||
|
|
||||||
UpdateNetworkGameWindow();
|
UpdateNetworkGameWindow();
|
||||||
|
|
||||||
|
@ -472,9 +472,8 @@ public:
|
|||||||
EM_ASM(if (window["openttd_server_list"]) openttd_server_list());
|
EM_ASM(if (window["openttd_server_list"]) openttd_server_list());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this->last_joined = NetworkGameListAddItem(ParseConnectionString(_settings_client.network.last_joined, NETWORK_DEFAULT_PORT));
|
this->last_joined = NetworkAddServer(_settings_client.network.last_joined);
|
||||||
this->server = this->last_joined;
|
this->server = this->last_joined;
|
||||||
if (this->last_joined != nullptr) NetworkUDPQueryServer(this->last_joined->address);
|
|
||||||
|
|
||||||
this->requery_timer.SetInterval(MILLISECONDS_PER_TICK);
|
this->requery_timer.SetInterval(MILLISECONDS_PER_TICK);
|
||||||
|
|
||||||
@ -750,7 +749,7 @@ public:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_NG_REFRESH: // Refresh
|
case WID_NG_REFRESH: // Refresh
|
||||||
if (this->server != nullptr) NetworkUDPQueryServer(this->server->address);
|
if (this->server != nullptr) NetworkTCPQueryServer(this->server->address);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_NG_NEWGRF: // NewGRF Settings
|
case WID_NG_NEWGRF: // NewGRF Settings
|
||||||
@ -971,7 +970,7 @@ void ShowNetworkGameWindow()
|
|||||||
first = false;
|
first = false;
|
||||||
/* Add all servers from the config file to our list. */
|
/* Add all servers from the config file to our list. */
|
||||||
for (const auto &iter : _network_host_list) {
|
for (const auto &iter : _network_host_list) {
|
||||||
NetworkAddServer(iter.c_str());
|
NetworkAddServer(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1485,7 +1484,7 @@ struct NetworkLobbyWindow : public Window {
|
|||||||
/* Clear the information so removed companies don't remain */
|
/* Clear the information so removed companies don't remain */
|
||||||
for (auto &company : this->company_info) company = {};
|
for (auto &company : this->company_info) company = {};
|
||||||
|
|
||||||
NetworkTCPQueryServer(this->server->address);
|
NetworkTCPQueryServer(this->server->address, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1555,7 +1554,7 @@ static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
|
|||||||
|
|
||||||
strecpy(_settings_client.network.last_joined, ngl->address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined));
|
strecpy(_settings_client.network.last_joined, ngl->address.GetAddressAsString(false).c_str(), lastof(_settings_client.network.last_joined));
|
||||||
|
|
||||||
NetworkTCPQueryServer(ngl->address);
|
NetworkTCPQueryServer(ngl->address, true);
|
||||||
|
|
||||||
new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
|
new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
|
||||||
}
|
}
|
||||||
|
@ -87,10 +87,10 @@ extern uint8 _network_reconnect;
|
|||||||
|
|
||||||
extern CompanyMask _network_company_passworded;
|
extern CompanyMask _network_company_passworded;
|
||||||
|
|
||||||
void NetworkTCPQueryServer(NetworkAddress address);
|
void NetworkTCPQueryServer(NetworkAddress address, bool request_company_info = false);
|
||||||
|
|
||||||
void GetBindAddresses(NetworkAddressList *addresses, uint16 port);
|
void GetBindAddresses(NetworkAddressList *addresses, uint16 port);
|
||||||
void NetworkAddServer(const char *b);
|
struct NetworkGameList *NetworkAddServer(const std::string &connection_string);
|
||||||
void NetworkRebuildHostList();
|
void NetworkRebuildHostList();
|
||||||
void UpdateNetworkGameWindow();
|
void UpdateNetworkGameWindow();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user