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() {
|
||||
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_server("localhost", 3979); */
|
||||
/* Add servers that support WebSocket here. Examples:
|
||||
* add_server("localhost");
|
||||
* add_server("localhost:3979");
|
||||
* add_server("127.0.0.1:3979");
|
||||
* add_server("[::1]:3979");
|
||||
*/
|
||||
}
|
||||
|
||||
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_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_SERVER_TOO_OLD :{WHITE}The queried server is too old for this client
|
||||
|
||||
############ Leave those lines in this order!!
|
||||
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 */
|
||||
class TCPQueryConnecter : TCPConnecter {
|
||||
private:
|
||||
bool request_company_info;
|
||||
|
||||
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
|
||||
{
|
||||
@ -613,36 +616,53 @@ public:
|
||||
void OnConnect(SOCKET s) override
|
||||
{
|
||||
_networking = true;
|
||||
new ClientNetworkGameSocketHandler(s);
|
||||
MyClient::SendInformationQuery();
|
||||
new ClientNetworkGameSocketHandler(s, address);
|
||||
MyClient::SendInformationQuery(request_company_info);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Query a server to fetch his game-info.
|
||||
* @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;
|
||||
|
||||
NetworkDisconnect();
|
||||
NetworkInitialize();
|
||||
|
||||
new TCPQueryConnecter(address);
|
||||
new TCPQueryConnecter(address, request_company_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an address entered as a string and adds the server to
|
||||
* the list. If you use this function, the games will be marked
|
||||
* 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
|
||||
{
|
||||
_networking = true;
|
||||
new ClientNetworkGameSocketHandler(s);
|
||||
new ClientNetworkGameSocketHandler(s, this->address);
|
||||
IConsoleCmdExec("exec scripts/on_client.scr 0");
|
||||
NetworkClient_Connected();
|
||||
}
|
||||
@ -1132,9 +1152,9 @@ void NetworkShutDown()
|
||||
#ifdef __EMSCRIPTEN__
|
||||
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.
|
||||
* @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);
|
||||
ClientNetworkGameSocketHandler::my_client = this;
|
||||
@ -345,14 +345,18 @@ static_assert(NETWORK_SERVER_ID_LENGTH == 16 * 2 + 1);
|
||||
/**
|
||||
* 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;
|
||||
_network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
|
||||
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));
|
||||
}
|
||||
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
@ -577,9 +581,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet *
|
||||
|
||||
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();
|
||||
if (item == nullptr) {
|
||||
/* This is not the lobby, so add it to the game list. */
|
||||
item = NetworkGameListAddItem(this->address);
|
||||
}
|
||||
|
||||
/* Clear any existing GRFConfig chain. */
|
||||
ClearGRFConfigList(&item->info.grfconfig);
|
||||
@ -590,6 +598,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packe
|
||||
/* Ensure we consider the server online. */
|
||||
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);
|
||||
|
||||
/* 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();
|
||||
|
||||
/* 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;
|
||||
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 */
|
||||
|
@ -15,12 +15,14 @@
|
||||
/** Class for handling the client side of the game connection. */
|
||||
class ClientNetworkGameSocketHandler : public ZeroedMemoryAllocator, public NetworkGameSocketHandler {
|
||||
private:
|
||||
NetworkAddress address; ///< Address we are connected to.
|
||||
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.
|
||||
|
||||
/** Status of the connection with the server. */
|
||||
enum ServerStatus {
|
||||
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_JOIN, ///< We are trying to join a server.
|
||||
STATUS_NEWGRFS_CHECK, ///< Last action was checking NewGRFs.
|
||||
@ -74,13 +76,13 @@ protected:
|
||||
static NetworkRecvStatus SendMapOk();
|
||||
void CheckConnection();
|
||||
public:
|
||||
ClientNetworkGameSocketHandler(SOCKET s);
|
||||
ClientNetworkGameSocketHandler(SOCKET s, NetworkAddress address);
|
||||
~ClientNetworkGameSocketHandler();
|
||||
|
||||
NetworkRecvStatus CloseConnection(NetworkRecvStatus status) override;
|
||||
void ClientError(NetworkRecvStatus res);
|
||||
|
||||
static NetworkRecvStatus SendInformationQuery();
|
||||
static NetworkRecvStatus SendInformationQuery(bool request_company_info);
|
||||
|
||||
static NetworkRecvStatus SendJoin();
|
||||
static NetworkRecvStatus SendCommand(const CommandPacket *cp);
|
||||
|
@ -69,15 +69,6 @@ static void NetworkGameListHandleDelayedInsert()
|
||||
*/
|
||||
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;
|
||||
|
||||
prev_item = nullptr;
|
||||
@ -95,7 +86,6 @@ NetworkGameList *NetworkGameListAddItem(NetworkAddress address)
|
||||
} else {
|
||||
prev_item->next = item;
|
||||
}
|
||||
DEBUG(net, 4, "[gamelist] added server to list");
|
||||
|
||||
UpdateNetworkGameWindow();
|
||||
|
||||
|
@ -472,9 +472,8 @@ public:
|
||||
EM_ASM(if (window["openttd_server_list"]) openttd_server_list());
|
||||
#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;
|
||||
if (this->last_joined != nullptr) NetworkUDPQueryServer(this->last_joined->address);
|
||||
|
||||
this->requery_timer.SetInterval(MILLISECONDS_PER_TICK);
|
||||
|
||||
@ -750,7 +749,7 @@ public:
|
||||
break;
|
||||
|
||||
case WID_NG_REFRESH: // Refresh
|
||||
if (this->server != nullptr) NetworkUDPQueryServer(this->server->address);
|
||||
if (this->server != nullptr) NetworkTCPQueryServer(this->server->address);
|
||||
break;
|
||||
|
||||
case WID_NG_NEWGRF: // NewGRF Settings
|
||||
@ -971,7 +970,7 @@ void ShowNetworkGameWindow()
|
||||
first = false;
|
||||
/* Add all servers from the config file to our 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 */
|
||||
for (auto &company : this->company_info) company = {};
|
||||
|
||||
NetworkTCPQueryServer(this->server->address);
|
||||
NetworkTCPQueryServer(this->server->address, true);
|
||||
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));
|
||||
|
||||
NetworkTCPQueryServer(ngl->address);
|
||||
NetworkTCPQueryServer(ngl->address, true);
|
||||
|
||||
new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
|
||||
}
|
||||
|
@ -87,10 +87,10 @@ extern uint8 _network_reconnect;
|
||||
|
||||
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 NetworkAddServer(const char *b);
|
||||
struct NetworkGameList *NetworkAddServer(const std::string &connection_string);
|
||||
void NetworkRebuildHostList();
|
||||
void UpdateNetworkGameWindow();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user