summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--os/emscripten/pre.js10
-rw-r--r--src/lang/english.txt1
-rw-r--r--src/network/network.cpp44
-rw-r--r--src/network/network_client.cpp35
-rw-r--r--src/network/network_client.h6
-rw-r--r--src/network/network_gamelist.cpp10
-rw-r--r--src/network/network_gui.cpp11
-rw-r--r--src/network/network_internal.h4
8 files changed, 78 insertions, 43 deletions
diff --git a/os/emscripten/pre.js b/os/emscripten/pre.js
index 1563e4f95..82664004e 100644
--- a/os/emscripten/pre.js
+++ b/os/emscripten/pre.js
@@ -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;
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 3037bf90f..f8e3618e5 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -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
diff --git a/src/network/network.cpp b/src/network/network.cpp
index d7cf9367a..c31a67487 100644
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -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;
+
+ 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);
- NetworkUDPQueryServer(ParseConnectionString(connection_string, NETWORK_DEFAULT_PORT), true);
+ 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);
}
}
diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp
index af7073e55..f73c8be52 100644
--- a/src/network/network_client.cpp
+++ b/src/network/network_client.cpp
@@ -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_COMPANY_INFO;
- _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
- SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
-
+ my_client->status = STATUS_GAME_INFO;
my_client->SendPacket(new Packet(PACKET_CLIENT_GAME_INFO));
- my_client->SendPacket(new Packet(PACKET_CLIENT_COMPANY_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_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 */
diff --git a/src/network/network_client.h b/src/network/network_client.h
index 66cdb8ba5..40b8eedf9 100644
--- a/src/network/network_client.h
+++ b/src/network/network_client.h
@@ -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);
diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp
index 6d4285c85..12dbbce61 100644
--- a/src/network/network_gamelist.cpp
+++ b/src/network/network_gamelist.cpp
@@ -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();
diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp
index 3204b2b96..590f2f5e0 100644
--- a/src/network/network_gui.cpp
+++ b/src/network/network_gui.cpp
@@ -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);
}
diff --git a/src/network/network_internal.h b/src/network/network_internal.h
index ff3c8c22d..683c954e8 100644
--- a/src/network/network_internal.h
+++ b/src/network/network_internal.h
@@ -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();