OpenTTD Source
20240917-master-g9ab0a47812
|
Go to the documentation of this file.
10 #include "../stdafx.h"
14 #include "../settings_type.h"
15 #include "../strings_func.h"
16 #include "../window_func.h"
17 #include "../window_type.h"
25 #include "table/strings.h"
27 #include "../safeguards.h"
55 void OnConnect(SOCKET s)
override
95 void OnConnect(SOCKET s)
override
117 void OnConnect(SOCKET s)
override
149 connecter_pre_it->second->SetFailure();
171 Debug(net, 0,
"Invalid error type {} received from Game Coordinator", error);
180 this->
next_update = std::chrono::steady_clock::now();
200 std::string connection_type;
208 default: connection_type =
"Unknown";
break;
211 std::string game_type;
213 case SERVER_GAME_TYPE_INVITE_ONLY: game_type =
"Invite only";
break;
214 case SERVER_GAME_TYPE_PUBLIC: game_type =
"Public";
break;
216 case SERVER_GAME_TYPE_LOCAL:
217 default: game_type =
"Unknown";
break;
220 Debug(net, 3,
"----------------------------------------");
221 Debug(net, 3,
"Your server is now registered with the Game Coordinator:");
222 Debug(net, 3,
" Game type: {}", game_type);
223 Debug(net, 3,
" Connection type: {}", connection_type);
225 Debug(net, 3,
"----------------------------------------");
243 for (; servers > 0; servers--) {
258 CheckGameCompatibility(item->
info);
275 auto connecter_pre_it = this->
connecter_pre.find(invite_code);
282 this->
connecter[token] = {invite_code, connecter_pre_it->second};
309 this->
game_connecter = TCPConnecter::Create<NetworkDirectConnecter>(hostname, port, token, tracking_number);
333 auto family_it = stun_it->second.find(family);
334 if (family_it == stun_it->second.end())
return true;
346 family_it->second->CloseConnection(
false);
352 this->
game_connecter = TCPConnecter::Create<NetworkReuseStunConnecter>(host, port, family_it->second->local_addr, token, tracking_number, family);
361 for (; newgrfs> 0; newgrfs--) {
384 auto connecter_it = this->
connecter.find(token);
385 if (connecter_it == this->
connecter.end()) {
401 this->StartTurnConnection(token);
405 this->StartTurnConnection(token);
411 void ClientNetworkCoordinatorSocketHandler::StartTurnConnection(std::string &token)
416 turn_it->second->Connect();
419 void ClientNetworkCoordinatorSocketHandler::Connect()
481 Debug(net, 6,
"Sending server update to Game Coordinator");
485 SerializeNetworkGameInfo(*p, GetCurrentNetworkServerGameInfo(), this->
next_update.time_since_epoch() != std::chrono::nanoseconds::zero());
504 p->Send_string(_openttd_revision);
517 assert(invite_code.starts_with(
"+"));
519 if (this->
connecter_pre.find(invite_code) != this->connecter_pre.end()) {
535 p->Send_string(invite_code);
552 p->Send_string(token);
553 p->Send_uint8(tracking_number);
569 assert(
sock != INVALID_SOCKET);
575 if (!ServerNetworkGameSocketHandler::ValidateClient(
sock, address))
return;
583 p->Send_string(token);
589 auto connecter_it = this->
connecter.find(token);
590 if (connecter_it != this->
connecter.end()) {
591 connecter_it->second.second->SetConnected(
sock);
611 p->Send_string(token);
612 p->Send_uint8(family);
613 p->Send_bool(result);
627 if (family == AF_UNSPEC) {
628 for (
auto &[family, stun_handler] : stun_it->second) {
629 stun_handler->CloseConnection();
630 stun_handler->CloseSocket();
635 auto family_it = stun_it->second.find(family);
636 if (family_it == stun_it->second.end())
return;
638 family_it->second->CloseConnection();
639 family_it->second->CloseSocket();
641 stun_it->second.erase(family_it);
656 turn_it->second->CloseConnection();
657 turn_it->second->CloseSocket();
675 auto connecter_it = this->
connecter.find(token);
676 if (connecter_it != this->
connecter.end()) {
677 connecter_it->second.second->SetFailure();
694 for (
auto &[token, it] : this->
connecter) {
697 it.second->SetFailure();
704 this->connecter.clear();
710 this->connecter_pre.clear();
721 if (this->
sock != INVALID_SOCKET) {
727 static int last_attempt_backoff = 1;
728 static bool first_reconnect =
true;
730 if (this->
sock == INVALID_SOCKET) {
731 static std::chrono::steady_clock::time_point last_attempt = {};
738 if (std::chrono::steady_clock::now() < last_attempt + std::chrono::seconds(1) * last_attempt_backoff)
return;
740 last_attempt = std::chrono::steady_clock::now();
742 if (last_attempt_backoff < 32) {
743 last_attempt_backoff *= 2;
750 if (first_reconnect) {
751 first_reconnect =
false;
755 Debug(net, 1,
"Connection with Game Coordinator lost; reconnecting...");
760 last_attempt_backoff = 1;
761 first_reconnect =
true;
781 for (
const auto &[family, stun_handler] : families) {
782 stun_handler->SendReceive();
787 for (
auto turn_it = this->
turn_handlers.begin(); turn_it != this->turn_handlers.end(); ) {
788 if (turn_it->second->connect_started && turn_it->second->connecter ==
nullptr && !turn_it->second->IsConnected()) {
795 for (
const auto &[token, turn_handler] : this->
turn_handlers) {
796 turn_handler->SendReceive();
The game information that is sent from the server to the clients with extra information only required...
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
static const uint16_t NETWORK_COORDINATOR_SERVER_PORT
The default port of the Game Coordinator server (TCP)
uint8_t tracking_number
Tracking number of this connection.
@ CONNECTION_TYPE_ISOLATED
The Game Coordinator failed to find a way to connect to your server. Nobody will be able to join.
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
std::string connection_string
Current address we are connecting to (before resolving).
static std::unique_ptr< ClientNetworkTurnSocketHandler > Turn(const std::string &token, uint8_t tracking_number, const std::string &ticket, const std::string &connection_string)
Prepare a TURN connection.
virtual void SendPacket(std::unique_ptr< Packet > &&packet)
This function puts the packet in the send-queue and it is send as soon as possible.
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
void ClearGRFConfigList(GRFConfig **config)
Clear a GRF Config list, freeing all nodes.
ConnectionType _network_server_connection_type
What type of connection the Game Coordinator detected we are on.
NetworkCoordinatorErrorType
The type of error from the Game Coordinator.
static const uint NETWORK_INVITE_CODE_SECRET_LENGTH
The maximum length of the invite code secret, in bytes including '\0'.
"Helper" class for creating TCP connections in a non-blocking manner
bool _network_server
network-server is active
const char * NetworkCoordinatorConnectionString()
Get the connection string for the game coordinator from the environment variable OTTD_COORDINATOR_CS,...
@ PACKET_COORDINATOR_SERVER_UPDATE
Server sends an set intervals an update of the server.
std::string server_invite_code_secret
Secret to proof we got this invite code from the Game Coordinator.
@ PACKET_COORDINATOR_CLIENT_CONNECTED
Client informs the Game Coordinator the connection with the server is established.
@ WC_CLIENT_LIST
Client list; Window numbers:
void ConnectFailure(const std::string &token, uint8_t tracking_number)
Callback from a Connecter to let the Game Coordinator know the connection failed.
static const uint8_t NETWORK_COORDINATOR_VERSION
What version of game-coordinator-protocol do we use?
@ CONNECTION_TYPE_DIRECT
The Game Coordinator can directly connect to your server.
void ConnectSuccess(const std::string &token, SOCKET sock, NetworkAddress &address)
Callback from a Connecter to let the Game Coordinator know the connection to the game server is estab...
SOCKET sock
The socket currently connected to.
static const char * GetName()
Get the name used by the listener.
bool Receive_GC_CONNECTING(Packet &p) override
Game Coordinator informs the Client under what token it will start the attempt to connect the Server ...
void CloseStunHandler(const std::string &token, uint8_t family=AF_UNSPEC)
Close the STUN handler.
void OnFailure() override
Callback for when the connection attempt failed.
ClientSettings _settings_client
The current settings for this game.
void UpdateNetworkGameWindow()
Update the network new window because a new server is found on the network.
NetworkGameList * NetworkGameListAddItem(const std::string &connection_string)
Add a new item to the linked gamelist.
static const auto NETWORK_COORDINATOR_DELAY_BETWEEN_UPDATES
How many time between updates the server sends to the Game Coordinator.
static const uint NETWORK_TOKEN_LENGTH
The maximum length of a token, in bytes including '\0'.
UseRelayService use_relay_service
Use relay service?
void StunResult(const std::string &token, uint8_t family, bool result)
Callback from the STUN connecter to inform the Game Coordinator about the result of the STUN.
@ NETWORK_COORDINATOR_ERROR_REUSE_OF_INVITE_CODE
The invite code is used by another (newer) server.
static NetworkAddress GetPeerAddress(SOCKET sock)
Get the peer address of a socket as NetworkAddress.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
bool Receive_GC_ERROR(Packet &p) override
Game Coordinator indicates there was an error.
void CloseAllConnections()
Close all pending connection tokens.
std::string Recv_string(size_t length, StringValidationSettings settings=SVS_REPLACE_WITH_QUESTION_MARK)
Reads characters (bytes) from the packet until it finds a '\0', or reaches a maximum of length charac...
@ PACKET_COORDINATOR_SERCLI_CONNECT_FAILED
Client/server tells the Game Coordinator the current connection attempt failed.
bool Receive_GC_LISTING(Packet &p) override
Game Coordinator replies with a list of all public servers.
std::string token
Token of this connection.
static const uint NETWORK_ERROR_DETAIL_LENGTH
The maximum length of the error detail, in bytes including '\0'.
@ PACKET_COORDINATOR_CLIENT_CONNECT
Client wants to connect to a server based on an invite code.
@ NETWORK_COORDINATOR_ERROR_INVALID_INVITE_CODE
The invite code given is invalid.
void ConnectToServer(const std::string &invite_code, TCPServerConnecter *connecter)
Join a server based on an invite code.
void Reopen()
Reopen the socket so we can send/receive stuff again.
uint32_t Recv_uint32()
Read a 32 bits integer from the packet.
NetworkReuseStunConnecter(const std::string &hostname, uint16_t port, const NetworkAddress &bind_address, std::string token, uint8_t tracking_number, uint8_t family)
Try to establish a STUN-based connection.
std::string token
Token of this connection.
bool Receive_GC_NEWGRF_LOOKUP(Packet &p) override
Game Coordinator informs the client of updates for the NewGRFs lookup table as used by the NewGRF des...
std::map< std::string, std::map< int, std::unique_ptr< ClientNetworkStunSocketHandler > > > stun_handlers
All pending STUN handlers, stored by token:family.
@ PACKET_COORDINATOR_SERCLI_STUN_RESULT
Client/server informs the Game Coordinator of the result of the STUN request.
NetworkRecvStatus CloseConnection(bool error=true) override
This will put this socket handler in a close state.
virtual NetworkRecvStatus CloseConnection(bool error=true)
This will put this socket handler in a close state.
int version
Used to see which servers are no longer available on the Game Coordinator and can be removed.
Connect to the Game Coordinator server.
uint32_t newgrf_lookup_table_cursor
Last received cursor for the #GameInfoNewGRFLookupTable updates.
static const size_t TCP_MTU
Number of bytes we can pack in a single TCP packet.
void GetListing()
Request a listing of all public servers.
std::shared_ptr< TCPConnecter > game_connecter
Pending connecter to the game server.
bool _network_dedicated
are we a dedicated server?
void Register()
Register our server to receive our invite code.
Internal entity of a packet.
static void AcceptConnection(SOCKET s, const NetworkAddress &address)
Handle the accepting of a connection to the server.
ConnectionType
The type of connection the Game Coordinator can detect we have.
@ NETWORK_COORDINATOR_ERROR_UNKNOWN
There was an unknown error.
void NetworkGameListRemoveExpired()
Remove all servers that have not recently been updated.
static const uint NETWORK_HOSTNAME_PORT_LENGTH
The maximum length of the host name + port, in bytes including '\0'. The extra six is ":" + port numb...
@ CONNECTION_TYPE_UNKNOWN
The Game Coordinator hasn't informed us yet what type of connection we have.
uint16_t server_port
port the server listens on
void OnFailure() override
Callback for when the connection attempt failed.
GameInfoNewGRFLookupTable newgrf_lookup_table
Table to look up NewGRFs in the GC_LISTING packets.
uint8_t tracking_number
Tracking number of this connection.
ServerGameType server_game_type
Server type: local / public / invite-only.
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
std::map< std::string, TCPServerConnecter * > connecter_pre
Based on invite codes, the current connecters that are pending.
bool CanSendReceive()
Check whether this socket can send or receive something.
@ PACKET_COORDINATOR_CLIENT_LISTING
Client is requesting a listing of all public servers.
void SendReceive()
Check whether we received/can send some data from/to the Game Coordinator server and when that's the ...
bool Receive_GC_STUN_CONNECT(Packet &p) override
Game Coordinator informs the client/server of its STUN peer (the host:ip of the other side).
uint32_t _frame_counter
The current frame.
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
std::chrono::steady_clock::time_point last_activity
The last time there was network activity.
Game Coordinator communication.
static const uint NETWORK_INVITE_CODE_LENGTH
The maximum length of the invite code, in bytes including '\0'.
Connecter used after STUN exchange to connect from both sides to each other.
ClientNetworkCoordinatorSocketHandler _network_coordinator_client
The connection to the Game Coordinator.
@ NGLS_ONLINE
Server is online.
std::string server_invite_code
Invite code to use when registering as server.
const std::string & GetHostname()
Get the hostname; in case it wasn't given the IPv4 dotted representation is given.
@ WC_NETWORK_ASK_RELAY
Network ask relay window; Window numbers:
static std::unique_ptr< ClientNetworkStunSocketHandler > Stun(const std::string &token, uint8_t family)
Send a STUN packet to the STUN server.
uint8_t family
Family of this connection.
void SendServerUpdate()
Send an update of our server status to the Game Coordinator.
@ CONNECTION_TYPE_TURN
The Game Coordinator needs you to connect to a relay.
NetworkCoordinatorConnecter(const std::string &connection_string)
Initiate the connecting.
bool Receive_GC_REGISTER_ACK(Packet &p) override
Game Coordinator acknowledges the registration.
std::chrono::steady_clock::time_point next_update
When to send the next update (if server and public).
@ WL_ERROR
Errors (eg. saving/loading failed)
bool Receive_GC_DIRECT_CONNECT(Packet &p) override
Game Coordinator requests that the Client makes a direct connection to the indicated peer,...
void OnFailure() override
Callback for when the connection attempt failed.
Structure with information shown in the game list (GUI)
std::map< std::string, std::unique_ptr< ClientNetworkTurnSocketHandler > > turn_handlers
Pending TURN handler (if any), stored by token.
@ NGLS_OFFLINE
Server is offline (or cannot be queried).
NetworkSettings network
settings related to the network
@ CONNECTION_TYPE_STUN
The Game Coordinator can connect to your server via a STUN request.
Connect to a game server by IP:port.
static const uint8_t NETWORK_GAME_INFO_VERSION
What version of game-info do we use?
static const uint NETWORK_HOSTNAME_LENGTH
The maximum length of the host name, in bytes including '\0'.
bool Receive_GC_CONNECT_FAILED(Packet &p) override
Game Coordinator informs the Client that it failed to find a way to connect the Client to the Server.
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
void CloseToken(const std::string &token)
Close everything related to this connection token.
void CloseTurnHandler(const std::string &token)
Close the TURN handler.
uint16_t Recv_uint16()
Read a 16 bits integer from the packet.
bool ReceivePackets()
Receive a packet at TCP level.
NetworkGameInfo info
The game information of this server.
int _network_game_list_version
Current version of all items in the list.
std::string _network_server_invite_code
Our invite code as indicated by the Game Coordinator.
@ NRWCD_HANDLED
Relay request is handled, either by user or by timeout.
@ PACKET_COORDINATOR_SERVER_REGISTER
Server registration.
GRFConfig * grfconfig
List of NewGRF files used.
NetworkAddress bind_address
Address we're binding to, if any.
std::map< std::string, std::pair< std::string, TCPServerConnecter * > > connecter
Based on tokens, the current (invite-code, connecter) that are pending.
void CloseSocket()
Close the actual socket of the connection.
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
bool Receive_GC_TURN_CONNECT(Packet &p) override
Game Coordinator requests that we make a connection to the indicated peer, which is a TURN server.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
@ NETWORK_COORDINATOR_ERROR_REGISTRATION_FAILED
Your request for registration failed.
bool Receive_GC_STUN_REQUEST(Packet &p) override
Game Coordinator requests the client/server to do a STUN request to the STUN server.
bool connecting
Are we connecting to the Game Coordinator?
void ShowNetworkAskRelay(const std::string &server_connection_string, const std::string &relay_connection_string, const std::string &token)
Show a modal confirmation window with "no" / "yes, once" / "yes, always" buttons.
static constexpr std::chrono::seconds IDLE_TIMEOUT
The idle timeout; when to close the connection because it's idle.
NetworkGameListStatus status
Stats of the server.
NetworkDirectConnecter(const std::string &hostname, uint16_t port, const std::string &token, uint8_t tracking_number)
Try to establish a direct (hostname:port based) connection.