SuperTuxKart
|
Represents the local host. More...
Public Member Functions | |
const SocketAddress & | getPublicAddress () 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 SocketAddress * | getStunIPv4Address () const |
const SocketAddress * | getStunIPv6Address () 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< STKPeer > | findPeerByHostId (uint32_t id) const |
std::shared_ptr< STKPeer > | findPeerByName (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< STKPeer > | getServerPeerForClient () 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) |
Network * | getNetwork () 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 |
NetworkTimerSynchronizer * | getNetworkTimerSynchronizer () 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) |
ChildLoop * | getChildLoop () const |
Static Public Member Functions | |
static std::shared_ptr< LobbyProtocol > | create (ChildLoop *cl=NULL) |
Creates the STKHost. | |
static STKHost * | get () |
Returns the instance of STKHost. | |
static STKHost * | getByType (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 | |
ChildLoop * | m_client_loop |
Separate process of server instance. | |
std::thread | m_client_loop_thread |
Network * | m_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< SocketAddress > | m_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< SocketAddress > | m_stun_ipv4 |
The public IPv4 address stun server used. | |
std::unique_ptr< SocketAddress > | m_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< NetworkTimerSynchronizer > | m_nts |
Static Private Attributes | |
static STKHost * | m_stk_host [PT_COUNT] |
Singleton pointer to the instance. | |
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:
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:
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:
|
private |
Destructor.
Stops the listening thread, closes the packet log file and destroys the enet host.
|
static |
Creates the STKHost.
It takes all confifguration parameters from NetworkConfig. This STKHost can either be a client or a server.
std::vector< std::shared_ptr< NetworkPlayerProfile > > STKHost::getPlayersForNewGame | ( | bool * | has_always_on_spectators = NULL | ) | const |
Get the players for starting a new game.
std::shared_ptr< STKPeer > STKHost::getServerPeerForClient | ( | ) | const |
|
static |
Get the stun network string required for binding request.
stun_tansaction_id | 16 bytes array for filling to validate later. |
|
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).
|
inline |
Returns true if this client instance is allowed to control the server.
It will auto transfer ownership if previous server owner disconnected.
|
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.
pt | : Used to register to different singleton. |
bool STKHost::peerExists | ( | const SocketAddress & | peer | ) |
Tells if a peer is known.
|
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.
void STKHost::sendPacketExcept | ( | STKPeer * | peer, |
NetworkString * | data, | ||
bool | reliable = true |
||
) |
Sends data to all validated peers except the specified currently in game.
peer | Peer which will not receive the message. |
data | Data to sent. |
reliable | If the data should be sent reliable or now. |
void STKHost::sendPacketToAllPeers | ( | NetworkString * | data, |
bool | reliable = true |
||
) |
Sends data to all validated peers currently in game.
data | Data to sent. |
reliable | If the data should be sent reliable or now. |
void STKHost::sendPacketToAllPeersInServer | ( | NetworkString * | data, |
bool | reliable = true |
||
) |
Sends data to all validated peers currently in server.
data | Data to sent. |
reliable | If the data should be sent reliable or now. |
void STKHost::sendPacketToAllPeersWith | ( | std::function< bool(STKPeer *)> | predicate, |
NetworkString * | data, | ||
bool | reliable = true |
||
) |
Sends data to peers with custom rule.
predicate | boolean function for peer to predicate whether to send |
data | Data to sent. |
reliable | If the data should be sent reliable or now. |
void STKHost::startListening | ( | ) |
Starts the listening of events from ENet.
Starts a thread for receiveData that updates it as often as possible.
void STKHost::stopListening | ( | ) |
Stops the listening of events from ENet.
Stops the thread that was receiving events.
void STKHost::updatePlayers | ( | unsigned * | ingame = NULL , |
unsigned * | waiting = NULL , |
||
unsigned * | total = NULL |
||
) |
Update players count in server.
ingame | store the in game players count now |
waiting | store the waiting players count now |
total | store the total players count now |
|
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.