SuperTuxKart
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Static Public Attributes | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
STKHost Class Reference

Represents the local host. More...

Public Member Functions

const SocketAddressgetPublicAddress () const
 
const std::string & getPublicIPv6Address () const
 
std::string getValidPublicAddress () const
 Return an valid public IPv4 or IPv6 address with port, empty if both are unset, IPv6 will come first if both exists.
 
const SocketAddressgetStunIPv4Address () const
 
const SocketAddressgetStunIPv6Address () const
 
uint16_t getPrivatePort () const
 
void setPublicAddress (short family)
 Set the public address using stun protocol.
 
void disconnectAllPeers (bool timeout_waiting=false)
 Disconnect all connected peers.
 
void requestShutdown ()
 Requests that the network infrastructure is to be shut down.
 
void shutdown ()
 Called from the main thread when the network infrastructure is to be shut down.
 
void sendPacketToAllPeersInServer (NetworkString *data, bool reliable=true)
 Sends data to all validated peers currently in server.
 
void sendPacketToAllPeers (NetworkString *data, bool reliable=true)
 Sends data to all validated peers currently in game.
 
void sendPacketToAllPeersWith (std::function< bool(STKPeer *)> predicate, NetworkString *data, bool reliable=true)
 Sends data to peers with custom rule.
 
bool isAuthorisedToControl () const
 Returns true if this client instance is allowed to control the server.
 
void setAuthorisedToControl (bool authorised)
 Sets if this local host is authorised to control the server.
 
std::vector< std::shared_ptr< NetworkPlayerProfile > > getAllPlayerProfiles () const
 
std::set< uint32_t > getAllPlayerOnlineIds () const
 
std::shared_ptr< STKPeerfindPeerByHostId (uint32_t id) const
 
std::shared_ptr< STKPeerfindPeerByName (const core::stringw &name) const
 
void sendPacketExcept (STKPeer *peer, NetworkString *data, bool reliable=true)
 Sends data to all validated peers except the specified currently in game.
 
void setupClient (int peer_count, int channel_limit, uint32_t max_incoming_bandwidth, uint32_t max_outgoing_bandwidth)
 
void startListening ()
 Starts the listening of events from ENet.
 
void stopListening ()
 Stops the listening of events from ENet.
 
bool peerExists (const SocketAddress &peer_address)
 Tells if a peer is known.
 
std::shared_ptr< STKPeergetServerPeerForClient () const
 Return the only server peer for client.
 
void setErrorMessage (const irr::core::stringw &message)
 Sets an error message for the gui.
 
void addEnetCommand (ENetPeer *peer, ENetPacket *packet, uint32_t i, ENetCommandType ect, ENetAddress ea)
 
const irr::core::stringw & getErrorMessage () const
 Returns the last error (or "" if no error has happened).
 
bool requestedShutdown () const
 Returns true if a shutdown of the network infrastructure was requested.
 
int receiveRawPacket (char *buffer, int buffer_len, SocketAddress *sender, int max_tries=-1)
 
void sendRawPacket (const BareNetworkString &buffer, const SocketAddress &dst)
 
NetworkgetNetwork () const
 
std::vector< std::shared_ptr< STKPeer > > getPeers () const
 Returns a copied list of peers.
 
unsigned int getNextHostId () const
 Returns the next (unique) host id.
 
void setNextHostId (uint32_t id)
 
unsigned int getPeerCount () const
 Returns the number of currently connected peers.
 
void setMyHostId (uint32_t my_host_id)
 Sets the global host id of this host (client use).
 
uint32_t getMyHostId () const
 Returns the host id of this host.
 
void sendToServer (NetworkString *data, bool reliable=true)
 Sends a message from a client to the server.
 
bool isClientServer () const
 True if this is a client and server in graphics mode made by server creation screen.
 
void initClientNetwork (ENetEvent &event, Network *new_network)
 
std::map< uint32_t, uint32_t > getPeerPings ()
 
uint32_t getClientPingToServer () const
 
NetworkTimerSynchronizergetNetworkTimerSynchronizer () const
 
uint64_t getNetworkTimer () const
 
void setNetworkTimer (uint64_t ticks)
 
std::pair< int, int > getAllPlayersTeamInfo () const
 
unsigned getUploadSpeed () const
 
unsigned getDownloadSpeed () const
 
void updatePlayers (unsigned *ingame=NULL, unsigned *waiting=NULL, unsigned *total=NULL)
 Update players count in server.
 
uint32_t getPlayersInGame () const
 
uint32_t getWaitingPlayers () const
 
uint32_t getTotalPlayers () const
 
std::vector< std::shared_ptr< NetworkPlayerProfile > > getPlayersForNewGame (bool *has_always_on_spectators=NULL) const
 Get the players for starting a new game.
 
void replaceNetwork (Network *new_network)
 
ChildLoopgetChildLoop () const
 

Static Public Member Functions

static std::shared_ptr< LobbyProtocolcreate (ChildLoop *cl=NULL)
 Creates the STKHost.
 
static STKHostget ()
 Returns the instance of STKHost.
 
static STKHostgetByType (ProcessType pt)
 
static void destroy ()
 
static bool existHost ()
 Checks if the STKHost has been created.
 
static void clear ()
 
static BareNetworkString getStunRequest (uint8_t *stun_tansaction_id)
 Get the stun network string required for binding request.
 

Static Public Attributes

static bool m_enable_console = false
 If a network console should be started.
 

Private Member Functions

 STKHost (bool server)
 The constructor for a server or client.
 
 ~STKHost ()
 Destructor.
 
void init ()
 Initialises the internal data structures and starts the protocol manager and the debug console.
 
void handleDirectSocketRequest (Network *direct_socket, std::shared_ptr< ServerLobby > sl, std::map< std::string, uint64_t > &ctp)
 Handles a direct request given to a socket.
 
void mainLoop (ProcessType pt)
 Thread function checking if data is received.
 
void getIPFromStun (int socket, const std::string &stun_address, short family, SocketAddress *result)
 

Private Attributes

ChildLoopm_client_loop
 Separate process of server instance.
 
std::thread m_client_loop_thread
 
Networkm_network
 ENet host interfacing sockets.
 
std::thread m_network_console
 Network console thread.
 
std::mutex m_peers_mutex
 Make sure the removing or adding a peer is thread-safe.
 
std::vector< std::tuple< ENetPeer *, ENetPacket *, uint32_t, ENetCommandType, ENetAddress > > m_enet_cmd
 Let (atm enet_peer_send and enet_peer_disconnect) run in the listening thread.
 
std::mutex m_enet_cmd_mutex
 Protect m_enet_cmd from multiple threads usage.
 
std::map< ENetPeer *, std::shared_ptr< STKPeer > > m_peers
 The list of peers connected to this instance.
 
uint32_t m_next_unique_host_id = 0
 Next unique host id.
 
uint32_t m_host_id = 0
 Host id of this host.
 
std::thread m_listening_thread
 Id of thread listening to enet events.
 
std::atomic_bool m_shutdown
 Flag which is set from the protocol manager thread which triggers a shutdown of the STKHost (and the Protocolmanager).
 
std::atomic_bool m_authorised
 True if this local host is authorised to control a server.
 
std::atomic< uint64_t > m_exit_timeout
 Use as a timeout to waiting a disconnect event when exiting.
 
irr::core::stringw m_error_message
 An error message, which is set by a protocol to be displayed in the GUI.
 
std::unique_ptr< SocketAddressm_public_address
 The public address found by stun (if WAN is used).
 
std::string m_public_ipv6_address
 The public IPv6 address found by stun (if WAN is used).
 
std::unique_ptr< SocketAddressm_stun_ipv4
 The public IPv4 address stun server used.
 
std::unique_ptr< SocketAddressm_stun_ipv6
 The public IPv6 address stun server used.
 
Synchronised< std::map< uint32_t, uint32_t > > m_peer_pings
 
std::atomic< uint32_t > m_client_ping
 
std::atomic< uint32_t > m_upload_speed
 
std::atomic< uint32_t > m_download_speed
 
std::atomic< uint32_t > m_players_in_game
 
std::atomic< uint32_t > m_players_waiting
 
std::atomic< uint32_t > m_total_players
 
std::atomic< int64_t > m_network_timer
 
std::unique_ptr< NetworkTimerSynchronizerm_nts
 

Static Private Attributes

static STKHostm_stk_host [PT_COUNT]
 Singleton pointer to the instance.
 

Detailed Description

Represents the local host.

It is the main managing point for networking. It is responsible for sending and receiving messages, and keeping track of connected peers. It also provides some low level socket functions (i.e. to avoid that enet adds its headers to messages, useful for broadcast in LAN and for stun). It can be either instantiated as server, or as client. Additionally this object stores information from the various protocols, which can be queried by the GUI. The online game works closely together with the stk server: a (game) server first connects to the stk server and registers itself, clients find the list of servers from the stk server. They insert a connections request into the stk server, which is regularly polled by the client. On detecting a new connection request the server will try to send a message to the client. This allows connections between server and client even if they are sitting behind a NAT firewall. The following tables on the stk server are used: client_sessions: It stores the list of all online users (so loging in means to insert a row in this table), including their token used for authentication. In case of a client or server, their public ip address and port number and private port (for LAN) are added to the entry. servers: Registers all servers and gives them a unique id, together with the user id (which is stored as host_id in this table). server_conn: This table stores connection requests from clients to servers. It has the aes_key and aes_iv which are used to validate clients if it's the same online user id joining a server, ip and port for NAT penetration and a connected_since which stores the timestamp the user joined this server to know the time playing spent playing on it.

The following outlines the protocol happening in order to connect a client to a server in more details:

First it calls setPublicAddress() here to discover the public ip address and port number of this host, Server:

  1. ServerLobby:
    1. Register this server with stk server (i.e. publish its public ip address, port number and game info) - 'create' request. This enters the server into the 'servers' table. This server can now be detected by other clients, so they can request a connection.
    2. The server lobby now polls the stk server for client connection requests using the 'poll-connection-requests' each 5 seconds, which queries the servers table to get the server id (based on address and user id), and then the server_conn table. The server will map each joined AES key within 45 seconds to each connected client to handle validation. Client:

The GUI queries the stk server to get a list of available servers ('get-all' request, submitted from ServersManager to query the 'servers' table). The user picks one (or in case of quick play one is picked randomly), and then instantiates STKHost with the id of this server. STKHost then triggers ConnectToServer, which do the following:

  1. Register the client with the STK host ('join-server-key' command, into the table 'server_conn'). Its public ip address and port will be registerd with a AES key and iv set by client.
  2. Run ConnectToServer::tryConnect for 30 seconds to connect to server, It will auto change to a correct server port in case the server is behind a strong firewall, see intercept below.

Server:

The ServerLobbyProtocol (SLP) will then detect the above client requests, and start a ConnectToPeer protocol for each incoming client. The ConnectToPeer protocol send client a raw packet with "0xffff" and "aloha-stk", so the client can use the intercept in enet for advanced NAT penetration, see ConnectToServer::interceptCallback for details.

Each client will run a ClientLobbyProtocol (CLP) to handle the further interaction with the server. The client will first request a connection with the server (this is for the 'logical' connection to the server; so far it was mostly about the 'physical' connection, i.e. being able to send a message to the server).

Each protocol has its own protocol id, which is added to each message in Protocol::sendMessage(). The ProtocolManager will automatically forward each received message to the protocol with the same id. So any message sent by protocol X on the server will be received by protocol X on the client and vice versa. The only exception are the client- and server-lobby: They share the same id (set in LobbyProtocol), so a message sent by the SLP will be received by the CLP, and a message from the CLP will be received by the SLP.

The server will reply with either a reject message (e.g. too many clients already connected), or an accept message. The accept message will contain the global player id of the client. Each time any client connect, disconnect or change team / handicap server will send a new list of currently available players and update them in the networking lobby.

When the authorised client or ownerless server timed up and start the kart selection, the SLP informs all clients to start the kart selection (SLP::startSelection). This triggers the creation of the kart selection (if grand prix in progress then goes track screen directly) screen in CLP::startSelection / CLP::update for all clients. The clients create the ActivePlayer object (which stores which device is used by which player).

After selecting a kart, the track selection screen is shown. On selecting a track, a vote for the track, laps and reversed is sent to the client (TrackScreen::eventCallback). The server will send all votes (track, #laps, ...) to all clients (see e.g. SLP::handlePlayerVote etc), which are handled in e.g. CLP::receivePlayerVote().

--> Server and all clients have identical information about all votes stored in m_peers_votes in LobbyProtocol base class.

The server will decide the best track vote based on the discussion from clients, then it will inform all clients to load the world (addAllPlayers) with the final players currently connected with team / handicap settings. Then (state LOAD_GAME) the server will load the world and wait for all clients to finish loading (WAIT_FOR_WORLD_LOADED).

In LR::loadWorld all ActivePlayers for all non-local players are created. (on a server all karts are non-local). On a client, the ActivePlayer objects for each local players have been created (to store the device used by each player when joining), so they are used to create the LocalPlayerController for each kart. Each remote player gets a NULL ActivePlayer (the ActivePlayer is only used for assigning the input device to each kart, achievements and highscores, so it's not needed for remote players). It will also start the RaceEventManager and then load the world.

Below you can see the definition of ping packet, it's a special packet that will be sent to each client waiting in lobby, the 1st byte is 255 so ProtocolManager won't handle it, after 5 bytes it comes with real data:

  1. Server time in uint64_t (for synchronization)
  2. Host id with ping to each client currently connected
  3. If game is currently started, 2 uint32_t which tell remaining time or progress in percent
  4. If game is currently started, the track internal identity

Constructor & Destructor Documentation

◆ ~STKHost()

STKHost::~STKHost ( )
private

Destructor.

Stops the listening thread, closes the packet log file and destroys the enet host.

Member Function Documentation

◆ create()

std::shared_ptr< LobbyProtocol > STKHost::create ( ChildLoop cl = NULL)
static

Creates the STKHost.

It takes all confifguration parameters from NetworkConfig. This STKHost can either be a client or a server.

◆ getPlayersForNewGame()

std::vector< std::shared_ptr< NetworkPlayerProfile > > STKHost::getPlayersForNewGame ( bool *  has_always_on_spectators = NULL) const

Get the players for starting a new game.

Returns
A vector containing pointers on the players profiles.

◆ getServerPeerForClient()

std::shared_ptr< STKPeer > STKHost::getServerPeerForClient ( ) const

Return the only server peer for client.

Returns
STKPeer the STKPeer of server.

◆ getStunRequest()

BareNetworkString STKHost::getStunRequest ( uint8_t *  stun_tansaction_id)
static

Get the stun network string required for binding request.

Parameters
stun_tansaction_id16 bytes array for filling to validate later.

◆ handleDirectSocketRequest()

void STKHost::handleDirectSocketRequest ( Network direct_socket,
std::shared_ptr< ServerLobby sl,
std::map< std::string, uint64_t > &  ctp 
)
private

Handles a direct request given to a socket.

This is typically a LAN request, but can also be used if the server is public (i.e. not behind a fire wall) to allow direct connection to the server (without using the STK server). It checks for any messages (i.e. a LAN broadcast requesting server details or a connection request) and if a valid LAN server-request message is received, will answer with a message containing server details (and sender IP address and port).

◆ isAuthorisedToControl()

bool STKHost::isAuthorisedToControl ( ) const
inline

Returns true if this client instance is allowed to control the server.

It will auto transfer ownership if previous server owner disconnected.

◆ mainLoop()

void STKHost::mainLoop ( ProcessType  pt)
private

Thread function checking if data is received.

This function tries to get data from network low-level functions as often as possible. When something is received, it generates an event and passes it to the Network Manager.

Parameters
pt: Used to register to different singleton.

◆ peerExists()

bool STKHost::peerExists ( const SocketAddress peer)

Tells if a peer is known.

Returns
True if the peer is known, false elseway.

◆ requestShutdown()

void STKHost::requestShutdown ( )
inline

Requests that the network infrastructure is to be shut down.

This function is called from a thread, but the actual shutdown needs to be done from the main thread to avoid race conditions (e.g. ProtocolManager might still access data structures when the main thread tests if STKHost exist (which it does, but ProtocolManager might be shut down already.

◆ sendPacketExcept()

void STKHost::sendPacketExcept ( STKPeer peer,
NetworkString data,
bool  reliable = true 
)

Sends data to all validated peers except the specified currently in game.

Parameters
peerPeer which will not receive the message.
dataData to sent.
reliableIf the data should be sent reliable or now.

◆ sendPacketToAllPeers()

void STKHost::sendPacketToAllPeers ( NetworkString data,
bool  reliable = true 
)

Sends data to all validated peers currently in game.

Parameters
dataData to sent.
reliableIf the data should be sent reliable or now.

◆ sendPacketToAllPeersInServer()

void STKHost::sendPacketToAllPeersInServer ( NetworkString data,
bool  reliable = true 
)

Sends data to all validated peers currently in server.

Parameters
dataData to sent.
reliableIf the data should be sent reliable or now.

◆ sendPacketToAllPeersWith()

void STKHost::sendPacketToAllPeersWith ( std::function< bool(STKPeer *)>  predicate,
NetworkString data,
bool  reliable = true 
)

Sends data to peers with custom rule.

Parameters
predicateboolean function for peer to predicate whether to send
dataData to sent.
reliableIf the data should be sent reliable or now.

◆ startListening()

void STKHost::startListening ( )

Starts the listening of events from ENet.

Starts a thread for receiveData that updates it as often as possible.

◆ stopListening()

void STKHost::stopListening ( )

Stops the listening of events from ENet.

Stops the thread that was receiving events.

◆ updatePlayers()

void STKHost::updatePlayers ( unsigned *  ingame = NULL,
unsigned *  waiting = NULL,
unsigned *  total = NULL 
)

Update players count in server.

Parameters
ingamestore the in game players count now
waitingstore the waiting players count now
totalstore the total players count now

Member Data Documentation

◆ m_next_unique_host_id

uint32_t STKHost::m_next_unique_host_id = 0
private

Next unique host id.

It is increased whenever a new peer is added (see getPeer()), but not decreased whena host (=peer) disconnects. This results in a unique host id for each host, even when a host should disconnect and then reconnect.


The documentation for this class was generated from the following files: