mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-11 13:10:45 +00:00
(svn r21361) -Change: make sure the client is listening, or rather receiving, our frames
This commit is contained in:
parent
21cf75951c
commit
31c8ab0ed8
@ -304,6 +304,7 @@ protected:
|
||||
* uint32 Frame counter max (how far may the client walk before the server?)
|
||||
* uint32 General seed 1 (dependant on compile settings, not default).
|
||||
* uint32 General seed 2 (dependant on compile settings, not default).
|
||||
* uint8 Random token to validate the client is actually listening (only occasionally present).
|
||||
*/
|
||||
DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FRAME);
|
||||
|
||||
@ -318,6 +319,7 @@ protected:
|
||||
/**
|
||||
* Tell the server we are done with this frame:
|
||||
* uint32 Current frame counter of the client.
|
||||
* uint8 The random token that the server sent in the PACKET_SERVER_FRAME packet.
|
||||
*/
|
||||
DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ACK);
|
||||
|
||||
|
@ -349,6 +349,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendAck()
|
||||
Packet *p = new Packet(PACKET_CLIENT_ACK);
|
||||
|
||||
p->Send_uint32(_frame_counter);
|
||||
p->Send_uint8 (my_client->token);
|
||||
my_client->SendPacket(p);
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
@ -798,7 +799,7 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_FRAME)
|
||||
#ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
|
||||
/* Test if the server supports this option
|
||||
* and if we are at the frame the server is */
|
||||
if (p->pos < p->size) {
|
||||
if (p->pos + 1 < p->size) {
|
||||
_sync_frame = _frame_counter_server;
|
||||
_sync_seed_1 = p->Recv_uint32();
|
||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||
@ -806,6 +807,9 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_FRAME)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/* Receive the token. */
|
||||
if (p->pos != p->size) this->token = p->Recv_uint8();
|
||||
|
||||
DEBUG(net, 5, "Received FRAME %d", _frame_counter_server);
|
||||
|
||||
/* Let the server know that we received this frame correctly
|
||||
|
@ -21,6 +21,7 @@ class ClientNetworkGameSocketHandler : public ZeroedMemoryAllocator, public Netw
|
||||
private:
|
||||
FILE *download_file; ///< Handle used for downloading the savegame.
|
||||
char *download_filename; ///< File name of the downloading savegame, so we open the right one.
|
||||
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 {
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "../roadveh.h"
|
||||
#include "../order_backup.h"
|
||||
#include "../core/pool_func.hpp"
|
||||
#include "../core/random_func.hpp"
|
||||
#include "../rev.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
@ -483,6 +484,13 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendFrame()
|
||||
p->Send_uint32(_sync_seed_2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* If token equals 0, we need to make a new token and send that. */
|
||||
if (this->last_token == 0) {
|
||||
this->last_token = InteractiveRandomRange(UINT8_MAX - 1) + 1;
|
||||
p->Send_uint8(this->last_token);
|
||||
}
|
||||
|
||||
this->SendPacket(p);
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
@ -982,11 +990,28 @@ DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_ACK)
|
||||
|
||||
/* Now he is! Unpause the game */
|
||||
this->status = STATUS_ACTIVE;
|
||||
this->last_token_frame = _frame_counter;
|
||||
|
||||
/* Execute script for, e.g. MOTD */
|
||||
IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
|
||||
}
|
||||
|
||||
/* Get, and validate the token. */
|
||||
uint8 token = p->Recv_uint8();
|
||||
if (token == this->last_token) {
|
||||
/* We differentiate between last_token_frame and last_frame so the lag
|
||||
* test uses the actual lag of the client instead of the lag for getting
|
||||
* the token back and forth; after all, the token is only sent every
|
||||
* time we receive a PACKET_CLIENT_ACK, after which we will send a new
|
||||
* token to the client. If the lag would be one day, then we would not
|
||||
* be sending the new token soon enough for the new daily scheduled
|
||||
* PACKET_CLIENT_ACK. This would then register the lag of the client as
|
||||
* two days, even when it's only a single day. */
|
||||
this->last_token_frame = _frame_counter;
|
||||
/* Request a new token. */
|
||||
this->last_token = 0;
|
||||
}
|
||||
|
||||
/* The client received the frame, make note of it */
|
||||
this->last_frame = frame;
|
||||
/* With those 2 values we can calculate the lag realtime */
|
||||
@ -1545,6 +1570,12 @@ void NetworkServer_Tick(bool send_frame)
|
||||
} else {
|
||||
cs->lag_test = 0;
|
||||
}
|
||||
if (cs->last_frame_server - cs->last_token_frame >= 5 * DAY_TICKS) {
|
||||
/* This is a bad client! It didn't send the right token back. */
|
||||
IConsolePrintF(CC_ERROR, "Client #%d is dropped because it fails to send valid acks", cs->client_id);
|
||||
cs->CloseConnection(NETWORK_RECV_STATUS_SERVER_ERROR);
|
||||
continue;
|
||||
}
|
||||
} else if (cs->status == NetworkClientSocket::STATUS_PRE_ACTIVE) {
|
||||
uint lag = NetworkCalculateLag(cs);
|
||||
if (lag > _settings_client.network.max_join_time) {
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
};
|
||||
|
||||
byte lag_test; ///< Byte used for lag-testing the client
|
||||
byte last_token; ///< The last random token we did send to verify the client is listening
|
||||
uint32 last_token_frame; ///< The last frame we received the right token
|
||||
ClientStatus status; ///< Status of this client
|
||||
CommandQueue outgoing_queue; ///< The command-queue awaiting delivery
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user