Update: Translations from eints
[openttd-github.git] / src / network / network_query.cpp
blob9f87a277f9f29f6523655325cafa74aa25b8e955
1 /*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
8 /** @file network_query.cpp Query part of the network protocol. */
10 #include "../stdafx.h"
11 #include "core/network_game_info.h"
12 #include "network_query.h"
13 #include "network_gamelist.h"
14 #include "../error.h"
16 #include "table/strings.h"
18 #include "../safeguards.h"
20 std::vector<std::unique_ptr<QueryNetworkGameSocketHandler>> QueryNetworkGameSocketHandler::queries = {};
22 NetworkRecvStatus QueryNetworkGameSocketHandler::CloseConnection(NetworkRecvStatus status)
24 assert(status != NETWORK_RECV_STATUS_OKAY);
25 assert(this->sock != INVALID_SOCKET);
27 /* Connection is closed, but we never received a packet. Must be offline. */
28 NetworkGameList *item = NetworkGameListAddItem(this->connection_string);
29 if (item->refreshing) {
30 item->status = NGLS_OFFLINE;
31 item->refreshing = false;
33 UpdateNetworkGameWindow();
36 return status;
39 /**
40 * Check the connection's state, i.e. is the connection still up?
42 bool QueryNetworkGameSocketHandler::CheckConnection()
44 std::chrono::steady_clock::duration lag = std::chrono::steady_clock::now() - this->last_packet;
46 /* If there was no response in 5 seconds, terminate the query. */
47 if (lag > std::chrono::seconds(5)) {
48 Debug(net, 0, "Timeout while waiting for response from {}", this->connection_string);
49 this->CloseConnection(NETWORK_RECV_STATUS_CONNECTION_LOST);
50 return false;
53 return true;
56 /**
57 * Check whether we received/can send some data from/to the server and
58 * when that's the case handle it appropriately.
59 * @return true when everything went okay.
61 bool QueryNetworkGameSocketHandler::Receive()
63 if (this->CanSendReceive()) {
64 NetworkRecvStatus res = this->ReceivePackets();
65 if (res != NETWORK_RECV_STATUS_OKAY) {
66 this->CloseConnection(res);
67 return false;
70 return true;
73 /** Send the packets of this socket handler. */
74 void QueryNetworkGameSocketHandler::Send()
76 this->SendPackets();
79 /**
80 * Query the server for server information.
82 NetworkRecvStatus QueryNetworkGameSocketHandler::SendGameInfo()
84 Debug(net, 9, "Query::SendGameInfo()");
86 this->SendPacket(std::make_unique<Packet>(this, PACKET_CLIENT_GAME_INFO));
87 return NETWORK_RECV_STATUS_OKAY;
90 NetworkRecvStatus QueryNetworkGameSocketHandler::Receive_SERVER_FULL(Packet &)
92 Debug(net, 9, "Query::Receive_SERVER_FULL()");
94 NetworkGameList *item = NetworkGameListAddItem(this->connection_string);
95 item->status = NGLS_FULL;
96 item->refreshing = false;
98 UpdateNetworkGameWindow();
100 return NETWORK_RECV_STATUS_CLOSE_QUERY;
103 NetworkRecvStatus QueryNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet &)
105 Debug(net, 9, "Query::Receive_SERVER_BANNED()");
107 NetworkGameList *item = NetworkGameListAddItem(this->connection_string);
108 item->status = NGLS_BANNED;
109 item->refreshing = false;
111 UpdateNetworkGameWindow();
113 return NETWORK_RECV_STATUS_CLOSE_QUERY;
116 NetworkRecvStatus QueryNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet &p)
118 Debug(net, 9, "Query::Receive_SERVER_GAME_INFO()");
120 NetworkGameList *item = NetworkGameListAddItem(this->connection_string);
122 /* Clear any existing GRFConfig chain. */
123 ClearGRFConfigList(&item->info.grfconfig);
124 /* Retrieve the NetworkGameInfo from the packet. */
125 DeserializeNetworkGameInfo(p, item->info);
126 /* Check for compatability with the client. */
127 CheckGameCompatibility(item->info);
128 /* Ensure we consider the server online. */
129 item->status = NGLS_ONLINE;
130 item->refreshing = false;
132 UpdateNetworkGameWindow();
134 return NETWORK_RECV_STATUS_CLOSE_QUERY;
137 NetworkRecvStatus QueryNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet &p)
139 NetworkErrorCode error = (NetworkErrorCode)p.Recv_uint8();
141 Debug(net, 9, "Query::Receive_SERVER_ERROR(): error={}", error);
143 NetworkGameList *item = NetworkGameListAddItem(this->connection_string);
145 if (error == NETWORK_ERROR_NOT_EXPECTED) {
146 /* If we query a server that is 1.11.1 or older, we get an
147 * NETWORK_ERROR_NOT_EXPECTED on requesting the game info. Show to the
148 * user this server is too old to query.
150 item->status = NGLS_TOO_OLD;
151 } else {
152 item->status = NGLS_OFFLINE;
154 item->refreshing = false;
156 UpdateNetworkGameWindow();
158 return NETWORK_RECV_STATUS_CLOSE_QUERY;
162 * Check if any query needs to send or receive.
164 /* static */ void QueryNetworkGameSocketHandler::SendReceive()
166 for (auto it = QueryNetworkGameSocketHandler::queries.begin(); it != QueryNetworkGameSocketHandler::queries.end(); /* nothing */) {
167 if (!(*it)->Receive()) {
168 it = QueryNetworkGameSocketHandler::queries.erase(it);
169 } else if (!(*it)->CheckConnection()) {
170 it = QueryNetworkGameSocketHandler::queries.erase(it);
171 } else {
172 it++;
176 for (auto &query : QueryNetworkGameSocketHandler::queries) {
177 query->Send();