|
|
|
@ -118,21 +118,20 @@ struct PacketWriter : SaveFilter {
|
|
|
|
|
/**
|
|
|
|
|
* Transfer all packets from here to the network's queue while holding
|
|
|
|
|
* the lock on our mutex.
|
|
|
|
|
* @param socket The network socket to write to.
|
|
|
|
|
* @return True iff the last packet of the map has been sent.
|
|
|
|
|
*/
|
|
|
|
|
bool TransferToNetworkQueue(ServerNetworkGameSocketHandler *socket)
|
|
|
|
|
bool TransferToNetworkQueue()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(this->mutex);
|
|
|
|
|
|
|
|
|
|
if (this->map_size_packet) {
|
|
|
|
|
/* Don't queue the PACKET_SERVER_MAP_SIZE before the corresponding PACKET_SERVER_MAP_BEGIN */
|
|
|
|
|
socket->SendPrependPacket(std::move(this->map_size_packet), PACKET_SERVER_MAP_BEGIN);
|
|
|
|
|
this->cs->SendPrependPacket(std::move(this->map_size_packet), PACKET_SERVER_MAP_BEGIN);
|
|
|
|
|
}
|
|
|
|
|
bool last_packet = false;
|
|
|
|
|
for (auto &p : this->packets) {
|
|
|
|
|
if (p->GetPacketType() == PACKET_SERVER_MAP_DONE) last_packet = true;
|
|
|
|
|
socket->SendPacket(std::move(p));
|
|
|
|
|
this->cs->SendPacket(std::move(p));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
this->packets.clear();
|
|
|
|
@ -142,13 +141,13 @@ struct PacketWriter : SaveFilter {
|
|
|
|
|
|
|
|
|
|
void Write(byte *buf, size_t size) override
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(this->mutex);
|
|
|
|
|
|
|
|
|
|
/* We want to abort the saving when the socket is closed. */
|
|
|
|
|
if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
|
|
|
|
|
|
|
|
|
|
if (this->current == nullptr) this->current = std::make_unique<Packet>(PACKET_SERVER_MAP_DATA, TCP_MTU);
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(this->mutex);
|
|
|
|
|
|
|
|
|
|
byte *bufe = buf + size;
|
|
|
|
|
while (buf != bufe) {
|
|
|
|
|
size_t written = this->current->Send_binary_until_full(buf, bufe);
|
|
|
|
@ -165,11 +164,11 @@ struct PacketWriter : SaveFilter {
|
|
|
|
|
|
|
|
|
|
void Finish() override
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(this->mutex);
|
|
|
|
|
|
|
|
|
|
/* We want to abort the saving when the socket is closed. */
|
|
|
|
|
if (this->cs == nullptr) SlError(STR_NETWORK_ERROR_LOSTCONNECTION);
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(this->mutex);
|
|
|
|
|
|
|
|
|
|
/* Make sure the last packet is flushed. */
|
|
|
|
|
if (this->current != nullptr) this->packets.push_back(std::move(this->current));
|
|
|
|
|
|
|
|
|
@ -489,6 +488,17 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendDesyncLog(const std::strin
|
|
|
|
|
NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck()
|
|
|
|
|
{
|
|
|
|
|
auto p = std::make_unique<Packet>(PACKET_SERVER_CHECK_NEWGRFS, TCP_MTU);
|
|
|
|
|
|
|
|
|
|
/* Invalid packet when status is anything but STATUS_INACTIVE. */
|
|
|
|
|
if (this->status != STATUS_INACTIVE) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
|
|
|
|
|
|
|
|
|
this->status = STATUS_NEWGRFS_CHECK;
|
|
|
|
|
|
|
|
|
|
if (_grfconfig == nullptr) {
|
|
|
|
|
/* There are no NewGRFs, continue with the game password. */
|
|
|
|
|
return this->SendNeedGamePassword();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const GRFConfig *c;
|
|
|
|
|
uint grf_count = 0;
|
|
|
|
|
|
|
|
|
@ -508,15 +518,16 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck()
|
|
|
|
|
/** Request the game password. */
|
|
|
|
|
NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedGamePassword()
|
|
|
|
|
{
|
|
|
|
|
/* Invalid packet when status is anything but STATUS_NEWGRFS_CHECK. */
|
|
|
|
|
if (this->status != STATUS_NEWGRFS_CHECK) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
|
|
|
|
|
|
|
|
|
this->status = STATUS_AUTH_GAME;
|
|
|
|
|
|
|
|
|
|
if (_settings_client.network.server_password.empty()) {
|
|
|
|
|
/* Do not actually need a game password, continue with the company password. */
|
|
|
|
|
return this->SendNeedCompanyPassword();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Invalid packet when status is STATUS_AUTH_GAME or higher */
|
|
|
|
|
if (this->status >= STATUS_AUTH_GAME) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
|
|
|
|
|
|
|
|
|
this->status = STATUS_AUTH_GAME;
|
|
|
|
|
/* Reset 'lag' counters */
|
|
|
|
|
this->last_frame = this->last_frame_server = _frame_counter;
|
|
|
|
|
|
|
|
|
@ -533,15 +544,16 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedGamePassword()
|
|
|
|
|
/** Request the company password. */
|
|
|
|
|
NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedCompanyPassword()
|
|
|
|
|
{
|
|
|
|
|
/* Invalid packet when status is anything but STATUS_AUTH_GAME. */
|
|
|
|
|
if (this->status != STATUS_AUTH_GAME) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
|
|
|
|
|
|
|
|
|
this->status = STATUS_AUTH_COMPANY;
|
|
|
|
|
|
|
|
|
|
NetworkClientInfo *ci = this->GetInfo();
|
|
|
|
|
if (!Company::IsValidID(ci->client_playas) || _network_company_states[ci->client_playas].password.empty()) {
|
|
|
|
|
return this->SendWelcome();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Invalid packet when status is STATUS_AUTH_COMPANY or higher */
|
|
|
|
|
if (this->status >= STATUS_AUTH_COMPANY) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
|
|
|
|
|
|
|
|
|
this->status = STATUS_AUTH_COMPANY;
|
|
|
|
|
/* Reset 'lag' counters */
|
|
|
|
|
this->last_frame = this->last_frame_server = _frame_counter;
|
|
|
|
|
|
|
|
|
@ -555,10 +567,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNeedCompanyPassword()
|
|
|
|
|
/** Send the client a welcome message with some basic information. */
|
|
|
|
|
NetworkRecvStatus ServerNetworkGameSocketHandler::SendWelcome()
|
|
|
|
|
{
|
|
|
|
|
/* Invalid packet when status is AUTH or higher */
|
|
|
|
|
if (this->status >= STATUS_AUTHORIZED) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
|
|
|
|
/* Invalid packet when status is anything but STATUS_AUTH_COMPANY. */
|
|
|
|
|
if (this->status != STATUS_AUTH_COMPANY) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET);
|
|
|
|
|
|
|
|
|
|
this->status = STATUS_AUTHORIZED;
|
|
|
|
|
|
|
|
|
|
/* Reset 'lag' counters */
|
|
|
|
|
this->last_frame = this->last_frame_server = _frame_counter;
|
|
|
|
|
|
|
|
|
@ -659,7 +672,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->status == STATUS_MAP) {
|
|
|
|
|
bool last_packet = this->savegame->TransferToNetworkQueue(this);
|
|
|
|
|
bool last_packet = this->savegame->TransferToNetworkQueue();
|
|
|
|
|
if (last_packet) {
|
|
|
|
|
/* Done reading, make sure saving is done as well */
|
|
|
|
|
this->savegame->Destroy();
|
|
|
|
@ -1015,13 +1028,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet &p)
|
|
|
|
|
/* Make sure companies to which people try to join are not autocleaned */
|
|
|
|
|
if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0;
|
|
|
|
|
|
|
|
|
|
this->status = STATUS_NEWGRFS_CHECK;
|
|
|
|
|
|
|
|
|
|
if (_grfconfig == nullptr) {
|
|
|
|
|
/* Continue asking for the game password. */
|
|
|
|
|
return this->SendNeedGamePassword();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this->SendNewGRFCheck();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|