Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -49,27 +49,17 @@ void SyncCMUser(const std::string &msg);
|
||||
|
||||
/** Read some packets, and when do use that data as initial load filter. */
|
||||
struct PacketReader : LoadFilter {
|
||||
static const size_t CHUNK = 32 * 1024; ///< 32 KiB chunks of memory.
|
||||
using Buffer = std::deque<uint8_t>; ///< The underlying buffer type that's being use.
|
||||
|
||||
std::vector<uint8_t *> blocks; ///< Buffer with blocks of allocated memory.
|
||||
uint8_t *buf; ///< Buffer we're going to write to/read from.
|
||||
uint8_t *bufe; ///< End of the buffer we write to/read from.
|
||||
uint8_t **block; ///< The block we're reading from/writing to.
|
||||
size_t written_bytes; ///< The total number of bytes we've written.
|
||||
size_t read_bytes; ///< The total number of read bytes.
|
||||
Buffer buffer; ///< Buffer with the raw save game data.
|
||||
Buffer::const_iterator iterator; ///< Buffer we're going to write to/read from.
|
||||
size_t read_bytes = 0; ///< The total number of read bytes.
|
||||
|
||||
/** Initialise everything. */
|
||||
PacketReader() : LoadFilter(nullptr), buf(nullptr), bufe(nullptr), block(nullptr), written_bytes(0), read_bytes(0)
|
||||
PacketReader() : LoadFilter(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
~PacketReader() override
|
||||
{
|
||||
for (auto p : this->blocks) {
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple wrapper around fwrite to be able to pass it to Packet's TransferOut.
|
||||
* @param destination The reader to add the data to.
|
||||
@@ -79,9 +69,7 @@ struct PacketReader : LoadFilter {
|
||||
*/
|
||||
static inline ssize_t TransferOutMemCopy(PacketReader *destination, const char *source, size_t amount)
|
||||
{
|
||||
memcpy(destination->buf, source, amount);
|
||||
destination->buf += amount;
|
||||
destination->written_bytes += amount;
|
||||
std::copy_n(source, amount, std::back_inserter(destination->buffer));
|
||||
return amount;
|
||||
}
|
||||
|
||||
@@ -92,47 +80,25 @@ struct PacketReader : LoadFilter {
|
||||
void AddPacket(Packet &p)
|
||||
{
|
||||
assert(this->read_bytes == 0);
|
||||
p.TransferOutWithLimit(TransferOutMemCopy, this->bufe - this->buf, this);
|
||||
|
||||
/* Did everything fit in the current chunk, then we're done. */
|
||||
if (p.RemainingBytesToTransfer() == 0) return;
|
||||
|
||||
/* Allocate a new chunk and add the remaining data. */
|
||||
this->blocks.push_back(this->buf = CallocT<uint8_t>(CHUNK));
|
||||
this->bufe = this->buf + CHUNK;
|
||||
|
||||
p.TransferOutWithLimit(TransferOutMemCopy, this->bufe - this->buf, this);
|
||||
p.TransferOut(TransferOutMemCopy, this);
|
||||
}
|
||||
|
||||
size_t Read(uint8_t *rbuf, size_t size) override
|
||||
{
|
||||
/* Limit the amount to read to whatever we still have. */
|
||||
size_t ret_size = size = std::min(this->written_bytes - this->read_bytes, size);
|
||||
this->read_bytes += ret_size;
|
||||
const uint8_t *rbufe = rbuf + ret_size;
|
||||
size_t read_size = std::min(this->buffer.size() - this->read_bytes, size);
|
||||
|
||||
while (rbuf != rbufe) {
|
||||
if (this->buf == this->bufe) {
|
||||
this->buf = *this->block++;
|
||||
this->bufe = this->buf + CHUNK;
|
||||
}
|
||||
std::copy_n(this->iterator, read_size, rbuf);
|
||||
std::advance(this->iterator, read_size);
|
||||
this->read_bytes += read_size;
|
||||
|
||||
size_t to_write = std::min(this->bufe - this->buf, rbufe - rbuf);
|
||||
memcpy(rbuf, this->buf, to_write);
|
||||
rbuf += to_write;
|
||||
this->buf += to_write;
|
||||
}
|
||||
|
||||
return ret_size;
|
||||
return read_size;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
this->read_bytes = 0;
|
||||
|
||||
this->block = this->blocks.data();
|
||||
this->buf = *this->block++;
|
||||
this->bufe = this->buf + CHUNK;
|
||||
this->iterator = this->buffer.cbegin();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -151,7 +117,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, const std::string &connection_string) : NetworkGameSocketHandler(s), connection_string(connection_string), savegame(nullptr), status(STATUS_INACTIVE)
|
||||
ClientNetworkGameSocketHandler::ClientNetworkGameSocketHandler(SOCKET s, const std::string &connection_string) : NetworkGameSocketHandler(s), connection_string(connection_string)
|
||||
{
|
||||
assert(ClientNetworkGameSocketHandler::my_client == nullptr);
|
||||
ClientNetworkGameSocketHandler::my_client = this;
|
||||
@@ -553,7 +519,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FULL(Packet &)
|
||||
Debug(net, 9, "Client::Receive_SERVER_FULL()");
|
||||
|
||||
/* We try to join a server which is full */
|
||||
ShowErrorMessage(STR_NETWORK_ERROR_SERVER_FULL, INVALID_STRING_ID, WL_CRITICAL);
|
||||
ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_SERVER_FULL), {}, WL_CRITICAL);
|
||||
|
||||
return NETWORK_RECV_STATUS_SERVER_FULL;
|
||||
}
|
||||
@@ -563,7 +529,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_BANNED(Packet &
|
||||
Debug(net, 9, "Client::Receive_SERVER_BANNED()");
|
||||
|
||||
/* We try to join a server where we are banned */
|
||||
ShowErrorMessage(STR_NETWORK_ERROR_SERVER_BANNED, INVALID_STRING_ID, WL_CRITICAL);
|
||||
ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_SERVER_BANNED), {}, WL_CRITICAL);
|
||||
|
||||
return NETWORK_RECV_STATUS_SERVER_BANNED;
|
||||
}
|
||||
@@ -604,8 +570,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac
|
||||
if (client_id == _network_own_client_id) SetLocalCompany(!Company::IsValidID(playas) ? COMPANY_SPECTATOR : playas);
|
||||
|
||||
ci->client_playas = playas;
|
||||
ci->client_name = name;
|
||||
ci->public_key = public_key;
|
||||
ci->client_name = std::move(name);
|
||||
ci->public_key = std::move(public_key);
|
||||
|
||||
citymania::SetClientListDirty();
|
||||
InvalidateWindowData(WC_CLIENT_LIST, 0);
|
||||
@@ -629,8 +595,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac
|
||||
ci->client_playas = playas;
|
||||
if (client_id == _network_own_client_id) this->SetInfo(ci);
|
||||
|
||||
ci->client_name = name;
|
||||
ci->public_key = public_key;
|
||||
ci->client_name = std::move(name);
|
||||
ci->public_key = std::move(public_key);
|
||||
|
||||
citymania::SetClientListDirty();
|
||||
InvalidateWindowData(WC_CLIENT_LIST, 0);
|
||||
@@ -679,10 +645,11 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet &p
|
||||
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 */
|
||||
if (error == NETWORK_ERROR_KICKED && p.CanReadFromPacket(1)) {
|
||||
SetDParamStr(0, p.Recv_string(NETWORK_CHAT_LENGTH));
|
||||
ShowErrorMessage(err, STR_NETWORK_ERROR_KICK_MESSAGE, WL_CRITICAL);
|
||||
ShowErrorMessage(GetEncodedString(err),
|
||||
GetEncodedString(STR_NETWORK_ERROR_KICK_MESSAGE, p.Recv_string(NETWORK_CHAT_LENGTH)),
|
||||
WL_CRITICAL);
|
||||
} else {
|
||||
ShowErrorMessage(err, INVALID_STRING_ID, WL_CRITICAL);
|
||||
ShowErrorMessage(GetEncodedString(err), {}, WL_CRITICAL);
|
||||
}
|
||||
|
||||
/* Perform an emergency save if we had already entered the game */
|
||||
@@ -709,7 +676,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(P
|
||||
const GRFConfig *f = FindGRFConfig(c.grfid, FGCM_EXACT, &c.md5sum);
|
||||
if (f == nullptr) {
|
||||
/* We do not know this GRF, bail out of initialization */
|
||||
Debug(grf, 0, "NewGRF {:08X} not found; checksum {}", BSWAP32(c.grfid), FormatArrayAsHex(c.md5sum));
|
||||
Debug(grf, 0, "NewGRF {:08X} not found; checksum {}", std::byteswap(c.grfid), FormatArrayAsHex(c.md5sum));
|
||||
ret = NETWORK_RECV_STATUS_NEWGRF_MISMATCH;
|
||||
}
|
||||
}
|
||||
@@ -720,7 +687,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHECK_NEWGRFS(P
|
||||
}
|
||||
|
||||
/* NewGRF mismatch, bail out */
|
||||
ShowErrorMessage(STR_NETWORK_ERROR_NEWGRF_MISMATCH, INVALID_STRING_ID, WL_CRITICAL);
|
||||
ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_NEWGRF_MISMATCH), {}, WL_CRITICAL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -731,7 +698,7 @@ class ClientGamePasswordRequestHandler : public NetworkAuthenticationPasswordReq
|
||||
if (!_network_join.server_password.empty()) {
|
||||
request->Reply(_network_join.server_password);
|
||||
} else {
|
||||
ShowNetworkNeedPassword(request);
|
||||
ShowNetworkNeedPassword(std::move(request));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -749,13 +716,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_AUTH_REQUEST(Pa
|
||||
_settings_client.network.client_secret_key, _settings_client.network.client_public_key);
|
||||
}
|
||||
switch (this->authentication_handler->ReceiveRequest(p)) {
|
||||
case NetworkAuthenticationClientHandler::READY_FOR_RESPONSE:
|
||||
case NetworkAuthenticationClientHandler::RequestResult::ReadyForResponse:
|
||||
return SendAuthResponse();
|
||||
|
||||
case NetworkAuthenticationClientHandler::AWAIT_USER_INPUT:
|
||||
case NetworkAuthenticationClientHandler::RequestResult::AwaitUserInput:
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
|
||||
case NetworkAuthenticationClientHandler::INVALID:
|
||||
case NetworkAuthenticationClientHandler::RequestResult::Invalid:
|
||||
default:
|
||||
return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||
}
|
||||
@@ -855,7 +822,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DATA(Packet
|
||||
/* We are still receiving data, put it to the file */
|
||||
this->savegame->AddPacket(p);
|
||||
|
||||
_network_join_bytes = (uint32_t)this->savegame->written_bytes;
|
||||
_network_join_bytes = static_cast<uint32_t>(this->savegame->buffer.size());
|
||||
SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
|
||||
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
@@ -887,7 +854,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
|
||||
this->last_packet = std::chrono::steady_clock::now();
|
||||
|
||||
if (!load_success) {
|
||||
ShowErrorMessage(STR_NETWORK_ERROR_SAVEGAMEERROR, INVALID_STRING_ID, WL_CRITICAL);
|
||||
ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_SAVEGAMEERROR), {}, WL_CRITICAL);
|
||||
return NETWORK_RECV_STATUS_SAVEGAME;
|
||||
}
|
||||
/* If the savegame has successfully loaded, ALL windows have been removed,
|
||||
@@ -914,7 +881,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
|
||||
Debug(net, 9, "Client::join_status = REGISTERING");
|
||||
_network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
|
||||
ShowJoinStatusWindow();
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_NEW, INVALID_COMPANY, CRR_NONE, _network_own_client_id);
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_NEW, CompanyID::Invalid(), CRR_NONE, _network_own_client_id);
|
||||
}
|
||||
} else {
|
||||
/* take control over an existing company */
|
||||
@@ -992,7 +959,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMMAND(Packet
|
||||
return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||
}
|
||||
|
||||
this->incoming_queue.push_back(cp);
|
||||
this->incoming_queue.push_back(std::move(cp));
|
||||
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
@@ -1027,9 +994,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHAT(Packet &p)
|
||||
/* For speaking to company, we need the company-name */
|
||||
case NETWORK_ACTION_CHAT_COMPANY: {
|
||||
StringID str = Company::IsValidID(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS;
|
||||
SetDParam(0, ci_to->client_playas);
|
||||
|
||||
name = GetString(str);
|
||||
name = GetString(str, ci_to->client_playas);
|
||||
ci = NetworkClientInfo::GetByClientID(_network_own_client_id);
|
||||
break;
|
||||
}
|
||||
@@ -1062,7 +1028,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_EXTERNAL_CHAT(P
|
||||
|
||||
if (!IsValidConsoleColour(colour)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||
|
||||
NetworkTextMessage(NETWORK_ACTION_EXTERNAL_CHAT, colour, false, user, msg, 0, source);
|
||||
NetworkTextMessage(NETWORK_ACTION_EXTERNAL_CHAT, colour, false, user, msg, source);
|
||||
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
@@ -1138,7 +1104,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_SHUTDOWN(Packet
|
||||
/* Only when we're trying to join we really
|
||||
* care about the server shutting down. */
|
||||
if (this->status >= STATUS_JOIN) {
|
||||
ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_SHUTDOWN, INVALID_STRING_ID, WL_CRITICAL);
|
||||
ShowErrorMessage(GetEncodedString(STR_NETWORK_MESSAGE_SERVER_SHUTDOWN), {}, WL_CRITICAL);
|
||||
}
|
||||
|
||||
if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave();
|
||||
@@ -1157,7 +1123,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_NEWGAME(Packet
|
||||
* Client ID modulo 16 + 1 (value 0 means no reconnect).
|
||||
* This way reconnects should be spread out a bit. */
|
||||
_network_reconnect = _network_own_client_id % 16 + 1;
|
||||
ShowErrorMessage(STR_NETWORK_MESSAGE_SERVER_REBOOT, INVALID_STRING_ID, WL_CRITICAL);
|
||||
ShowErrorMessage(GetEncodedString(STR_NETWORK_MESSAGE_SERVER_REBOOT), {}, WL_CRITICAL);
|
||||
}
|
||||
|
||||
if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave();
|
||||
@@ -1251,8 +1217,10 @@ void ClientNetworkGameSocketHandler::CheckConnection()
|
||||
if (std::chrono::duration_cast<std::chrono::seconds>(last_lag) == std::chrono::duration_cast<std::chrono::seconds>(lag)) return;
|
||||
|
||||
last_lag = lag;
|
||||
SetDParam(0, std::chrono::duration_cast<std::chrono::seconds>(lag).count());
|
||||
ShowErrorMessage(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION, STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION, WL_INFO);
|
||||
ShowErrorMessage(
|
||||
GetEncodedString(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION),
|
||||
GetEncodedString(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION, std::chrono::duration_cast<std::chrono::seconds>(lag).count()),
|
||||
WL_INFO);
|
||||
}
|
||||
|
||||
|
||||
@@ -1342,7 +1310,7 @@ bool NetworkValidateClientName(std::string &client_name)
|
||||
StrTrimInPlace(client_name);
|
||||
if (NetworkIsValidClientName(client_name)) return true;
|
||||
|
||||
ShowErrorMessage(STR_NETWORK_ERROR_BAD_PLAYER_NAME, INVALID_STRING_ID, WL_ERROR);
|
||||
ShowErrorMessage(GetEncodedString(STR_NETWORK_ERROR_BAD_PLAYER_NAME), {}, WL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1376,7 +1344,7 @@ void NetworkUpdateClientName(const std::string &client_name)
|
||||
std::string temporary_name = client_name;
|
||||
if (NetworkMakeClientNameUnique(temporary_name)) {
|
||||
NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name);
|
||||
ci->client_name = temporary_name;
|
||||
ci->client_name = std::move(temporary_name);
|
||||
NetworkUpdateClientInfo(CLIENT_ID_SERVER);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user