osb/source/server/StarServerQueryThread.hpp
2023-06-20 14:33:09 +10:00

109 lines
3.4 KiB
C++

#ifndef STAR_SERVER_QUERY_THREAD_HPP
#define STAR_SERVER_QUERY_THREAD_HPP
#include "StarThread.hpp"
#include "StarHostAddress.hpp"
#include "StarUdp.hpp"
#include "StarMap.hpp"
#include "StarDataStreamDevices.hpp"
#include <random>
namespace Star {
STAR_CLASS(UniverseServer);
STAR_CLASS(ServerQueryThread);
class ServerQueryThread : public Thread {
public:
ServerQueryThread(UniverseServer* universe, HostAddressWithPort const& bindAddress);
~ServerQueryThread();
void start();
void stop();
protected:
virtual void run();
private:
static const uint8_t A2A_PING_REQUEST = 0x69;
static const uint8_t A2A_PING_REPLY = 0x6a;
static const uint8_t A2S_CHALLENGE_REQUEST = 0x57;
static const uint8_t A2S_CHALLENGE_RESPONSE = 0x41;
static const uint8_t A2S_INFO_REQUEST = 0x54;
static const uint8_t A2S_INFO_REPLY = 0x49;
static const uint8_t A2S_PLAYER_REQUEST = 0x55;
static const uint8_t A2S_PLAYER_REPLY = 0x44;
static const uint8_t A2S_RULES_REQUEST = 0x56;
static const uint8_t A2S_RULES_REPLY = 0x45;
static const uint8_t A2S_VERSION = 0x07;
static const uint8_t A2S_STR_TERM = 0x00;
static const uint8_t A2S_EDF_GID = 0x01;
static const uint8_t A2S_EDF_SID = 0x10;
static const uint8_t A2S_EDF_TAGS = 0x20;
static const uint8_t A2S_EDF_STV = 0x40;
static const uint8_t A2S_EDF_PORT = 0x80;
static const uint8_t A2S_ENV_WINDOWS = 'W';
static const uint8_t A2S_ENV_LINUX = 'L';
static const uint8_t A2S_TYPE_DEDICATED = 'D';
static const uint8_t A2S_TYPE_LISTEN = 'L';
static const uint8_t A2S_TYPE_TV = 'P';
static const uint8_t A2S_VAC_OFF = 0x00;
static const uint8_t A2S_VAC_ON = 0x01;
static constexpr const char* A2S_INFO_REQUEST_STRING = "Source Engine Query";
static const uint16_t A2S_APPID = (uint16_t)0xfffe;
static const uint16_t A2S_PACKET_SIZE = (uint16_t)0x4e0;
static const uint32_t A2S_HEAD_INT = 0xffffffff;
static constexpr const char* GAME_DIR = "starbound";
static constexpr const char* GAME_DESC = "Starbound";
static constexpr const char* GAME_TYPE = "SMP";
static const int32_t challengeCheckInterval = 30000;
static const int32_t responseCacheTime = 5000;
void sendTo(HostAddressWithPort const& address, DataStreamBuffer* ds);
bool processPacket(HostAddressWithPort const& address, char const* data, size_t length);
void buildPlayerResponse();
void buildRuleResponse();
bool validChallenge(HostAddressWithPort const& address, char const* data, size_t length);
void sendChallenge(HostAddressWithPort const& address);
void pruneChallenges();
bool challengeRequest(HostAddressWithPort const& address, char const* data, size_t length);
// Server API
uint8_t serverPlayerCount();
bool serverPassworded();
const char* serverPlugins();
String serverWorldNames();
UniverseServer* m_universe;
UdpServer m_queryServer;
bool m_stop;
DataStreamBuffer m_playersResponse;
DataStreamBuffer m_rulesResponse;
DataStreamBuffer m_generalResponse;
class RequestChallenge {
public:
RequestChallenge();
bool before(uint64_t time);
int32_t getChallenge();
private:
uint64_t m_time;
int32_t m_challenge;
};
uint16_t m_serverPort;
uint8_t m_maxPlayers;
String m_serverName;
HashMap<HostAddress, shared_ptr<RequestChallenge>> m_validChallenges;
int64_t m_lastChallengeCheck;
int64_t m_lastPlayersResponse;
int64_t m_lastRulesResponse;
int64_t m_lastActiveTime;
};
}
#endif