mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-22 14:55:36 +08:00
588 lines
28 KiB
C++
588 lines
28 KiB
C++
/* Copyright (C) 2019
|
|
* swift project community / contributors
|
|
*
|
|
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
|
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
|
* or distributed except according to the terms contained in the LICENSE file.
|
|
*/
|
|
|
|
//! \file
|
|
|
|
#ifndef BLACKCORE_FSD_CLIENT_H
|
|
#define BLACKCORE_FSD_CLIENT_H
|
|
|
|
#include "blackcore/blackcoreexport.h"
|
|
#include "blackcore/vatsim/vatsimsettings.h"
|
|
#include "blackcore/fsd/enums.h"
|
|
#include "blackcore/fsd/messagebase.h"
|
|
|
|
#include "blackmisc/simulation/ownaircraftprovider.h"
|
|
#include "blackmisc/simulation/remoteaircraftprovider.h"
|
|
#include "blackmisc/simulation/simulationenvironmentprovider.h"
|
|
#include "blackmisc/aviation/atcstationlist.h"
|
|
#include "blackmisc/aviation/callsign.h"
|
|
#include "blackmisc/aviation/flightplan.h"
|
|
#include "blackmisc/aviation/informationmessage.h"
|
|
#include "blackmisc/aviation/aircrafticaocode.h"
|
|
#include "blackmisc/network/rawfsdmessage.h"
|
|
#include "blackmisc/network/connectionstatus.h"
|
|
#include "blackmisc/network/loginmode.h"
|
|
#include "blackmisc/network/server.h"
|
|
#include "blackmisc/network/ecosystemprovider.h"
|
|
#include "blackmisc/network/clientprovider.h"
|
|
#include "blackmisc/network/textmessagelist.h"
|
|
#include "blackmisc/worker.h"
|
|
#include "blackmisc/digestsignal.h"
|
|
#include "blackmisc/tokenbucket.h"
|
|
|
|
#include "vatsim/vatsimauth.h"
|
|
|
|
#include <QtGlobal>
|
|
#include <QHash>
|
|
#include <QString>
|
|
#include <QObject>
|
|
#include <QTcpSocket>
|
|
#include <QCommandLineOption>
|
|
#include <QTimer>
|
|
#include <QTextCodec>
|
|
#include <QReadWriteLock>
|
|
#include <QQueue>
|
|
|
|
#include <atomic>
|
|
|
|
//! Protocol version
|
|
//! @{
|
|
#define PROTOCOL_REVISION_CLASSIC 9
|
|
#define PROTOCOL_REVISION_VATSIM_ATC 10
|
|
#define PROTOCOL_REVISION_VATSIM_AUTH 100
|
|
#define PROTOCOL_REVISION_VATSIM_VELOCITY 101
|
|
//! @}
|
|
|
|
namespace BlackFsdTest { class CTestFSDClient; }
|
|
namespace BlackCore::Fsd
|
|
{
|
|
//! Message groups
|
|
enum class TextMessageGroups
|
|
{
|
|
AllClients,
|
|
AllAtcClients,
|
|
AllPilotClients,
|
|
AllSups
|
|
};
|
|
|
|
//! FSD client
|
|
//! Todo: Send (interim) data updates automatically
|
|
//! Todo Check ':' in FSD messages. Disconnect if there is a wrong one
|
|
class BLACKCORE_EXPORT CFSDClient :
|
|
public BlackMisc::CContinuousWorker,
|
|
public BlackMisc::Network::IEcosystemProvider, // provide info about used ecosystem
|
|
public BlackMisc::Network::CClientAware, // network can set client information
|
|
public BlackMisc::Simulation::COwnAircraftAware, // network vatlib consumes own aircraft data and sets ICAO/callsign data
|
|
public BlackMisc::Simulation::CRemoteAircraftAware, // check if we really need to process network packets (e.g. parts)
|
|
public BlackMisc::Simulation::CSimulationEnvironmentAware // allows to consume ground elevations
|
|
{
|
|
Q_OBJECT
|
|
Q_INTERFACES(BlackMisc::Network::IEcosystemProvider)
|
|
|
|
public:
|
|
//! Categories
|
|
static const QStringList &getLogCategories();
|
|
|
|
//! Ctor
|
|
CFSDClient(BlackMisc::Network::IClientProvider *clientProvider,
|
|
BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider,
|
|
BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraftProvider,
|
|
QObject *owner = nullptr);
|
|
|
|
//! Preset functions
|
|
//! \remark Necessary functions to setup client. Set them all!
|
|
//! \threadsafe
|
|
//! @{
|
|
void setClientName(const QString &clientName) { QWriteLocker l(&m_lockUserClientBuffered); m_clientName = clientName; }
|
|
void setHostApplication(const QString &hostApplication) { QWriteLocker l(&m_lockUserClientBuffered); m_hostApplication = hostApplication; }
|
|
void setVersion(int major, int minor) { QWriteLocker l(&m_lockUserClientBuffered); m_versionMajor = major; m_versionMinor = minor; }
|
|
void setClientIdAndKey(quint16 id, const QByteArray &key);
|
|
void setClientCapabilities(Capabilities capabilities) { QWriteLocker l(&m_lockUserClientBuffered); m_capabilities = capabilities; }
|
|
void setServer(const BlackMisc::Network::CServer &server);
|
|
void setLoginMode(const BlackMisc::Network::CLoginMode &mode) { QWriteLocker l(&m_lockUserClientBuffered); m_loginMode = mode; }
|
|
void setCallsign(const BlackMisc::Aviation::CCallsign &callsign);
|
|
void setPartnerCallsign(const BlackMisc::Aviation::CCallsign &callsign) { QWriteLocker l(&m_lockUserClientBuffered); m_partnerCallsign = callsign; }
|
|
void setIcaoCodes(const BlackMisc::Simulation::CSimulatedAircraft &ownAircraft);
|
|
void setLiveryAndModelString(const QString &livery, bool sendLiveryString, const QString &modelString, bool sendModelString);
|
|
void setSimType(const BlackMisc::Simulation::CSimulatorInfo &simInfo);
|
|
void setSimType(BlackMisc::Simulation::CSimulatorInfo::Simulator simulator);
|
|
void setPilotRating(PilotRating rating) { QWriteLocker l(&m_lockUserClientBuffered); m_pilotRating = rating; }
|
|
void setAtcRating(AtcRating rating) { QWriteLocker l(&m_lockUserClientBuffered); m_atcRating = rating; }
|
|
//! @}
|
|
|
|
// ------ thread safe access to preset values -----
|
|
|
|
//! Get the server
|
|
//! \threadsafe
|
|
const BlackMisc::Network::CServer &getServer() const { QReadLocker l(&m_lockUserClientBuffered); return m_server; }
|
|
|
|
//! List of all preset values
|
|
//! \threadsafe
|
|
QStringList getPresetValues() const;
|
|
|
|
//! Callsign if any
|
|
//! \threadsafe
|
|
BlackMisc::Aviation::CCallsign getPresetCallsign() const { QReadLocker l(&m_lockUserClientBuffered); return m_ownCallsign; }
|
|
|
|
//! Partner callsign if any
|
|
//! \threadsafe
|
|
BlackMisc::Aviation::CCallsign getPresetPartnerCallsign() const { QReadLocker l(&m_lockUserClientBuffered); return m_partnerCallsign; }
|
|
|
|
//! Mode
|
|
//! \threadsafe
|
|
BlackMisc::Network::CLoginMode getLoginMode() const { QReadLocker l(&m_lockUserClientBuffered); return m_loginMode; }
|
|
|
|
//! Rating
|
|
//! \threadsafe
|
|
PilotRating getPilotRating() const { QReadLocker l(&m_lockUserClientBuffered); return m_pilotRating; }
|
|
|
|
//! Connenct/disconnect
|
|
//! @{
|
|
void connectToServer();
|
|
void disconnectFromServer();
|
|
//! @}
|
|
|
|
//! Interim positions
|
|
//! @{
|
|
void addInterimPositionReceiver(const BlackMisc::Aviation::CCallsign &receiver) { m_interimPositionReceivers.push_back(receiver); }
|
|
void removeInterimPositionReceiver(const BlackMisc::Aviation::CCallsign &receiver) { m_interimPositionReceivers.remove(receiver); }
|
|
//! @}
|
|
|
|
//! Convenience functions for sendClientQuery
|
|
//! \remark pseudo private, used in CAirspaceMonitor and network context
|
|
//! \private
|
|
//! @{
|
|
void sendClientQueryCapabilities(const BlackMisc::Aviation::CCallsign &callsign);
|
|
void sendClientQueryCom1Freq(const BlackMisc::Aviation::CCallsign &callsign);
|
|
void sendClientQueryRealName(const BlackMisc::Aviation::CCallsign &callsign);
|
|
void sendClientQueryServer(const BlackMisc::Aviation::CCallsign &callsign);
|
|
void sendClientQueryAtis(const BlackMisc::Aviation::CCallsign &callsign);
|
|
void sendClientQueryFlightPlan(const BlackMisc::Aviation::CCallsign &callsign);
|
|
void sendClientQueryAircraftConfig(const BlackMisc::Aviation::CCallsign &callsign);
|
|
void sendTextMessages(const BlackMisc::Network::CTextMessageList &messages);
|
|
void sendTextMessage(const BlackMisc::Network::CTextMessage &message);
|
|
void sendTextMessage(TextMessageGroups receiverGroup, const QString &message);
|
|
void sendRadioMessage(const QVector<int> &frequencieskHz, const QString &message);
|
|
void sendFlightPlan(const BlackMisc::Aviation::CFlightPlan &flightPlan);
|
|
void sendPlaneInfoRequest(const BlackMisc::Aviation::CCallsign &receiver);
|
|
void sendPlaneInfoRequestFsinn(const BlackMisc::Aviation::CCallsign &callsign);
|
|
//! @}
|
|
|
|
//! Interim pos.receivers
|
|
//! @{
|
|
BlackMisc::Aviation::CCallsignSet getInterimPositionReceivers() const;
|
|
void setInterimPositionReceivers(const BlackMisc::Aviation::CCallsignSet &interimPositionReceivers);
|
|
//! @}
|
|
|
|
//! Connection status
|
|
//! @{
|
|
BlackMisc::Network::CConnectionStatus getConnectionStatus() const { QReadLocker l(&m_lockConnectionStatus); return m_connectionStatus; }
|
|
bool isConnected() const { return this->getConnectionStatus().isConnected(); }
|
|
bool isDisconnected() const { return this->getConnectionStatus().isDisconnected(); }
|
|
bool isPendingConnection() const;
|
|
//! @}
|
|
|
|
//! Statistics enable functions
|
|
//! @{
|
|
bool setStatisticsEnable(bool enabled) { m_statistics = enabled; return enabled; }
|
|
bool isStatisticsEnabled() const { return m_statistics; }
|
|
//! @}
|
|
|
|
//! Clear the statistics
|
|
void clearStatistics();
|
|
|
|
//! Text statistics
|
|
QString getNetworkStatisticsAsText(bool reset, const QString &separator = "\n");
|
|
|
|
//! Debugging and UNIT tests
|
|
void printToConsole(bool on) { m_printToConsole = on; }
|
|
|
|
//! Gracefully shut down FSD client
|
|
void gracefulShutdown();
|
|
|
|
signals:
|
|
//! Client responses received
|
|
//! @{
|
|
void atcDataUpdateReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CFrequency &freq,
|
|
const BlackMisc::Geo::CCoordinateGeodetic &pos, const BlackMisc::PhysicalQuantities::CLength &range);
|
|
void deleteAtcReceived(const QString &cid);
|
|
void deletePilotReceived(const QString &cid);
|
|
void pilotDataUpdateReceived(const BlackMisc::Aviation::CAircraftSituation &situation, const BlackMisc::Aviation::CTransponder &transponder);
|
|
void pongReceived(const QString &sender, double elapsedTimeMs);
|
|
void flightPlanReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CFlightPlan &flightPlan);
|
|
void textMessagesReceived(const BlackMisc::Network::CTextMessageList &messages);
|
|
void aircraftConfigReceived(const QString &sender, const QJsonObject &config, qint64 currentOffsetTimeMs);
|
|
void validAtcResponseReceived(const QString &callsign, bool isValidAtc);
|
|
void capabilityResponseReceived(const BlackMisc::Aviation::CCallsign &sender, BlackMisc::Network::CClient::Capabilities capabilities);
|
|
void com1FrequencyResponseReceived(const QString &sender, const BlackMisc::PhysicalQuantities::CFrequency &frequency);
|
|
void realNameResponseReceived(const QString &sender, const QString &realName);
|
|
void serverResponseReceived(const QString &sender, const QString &hostName);
|
|
void planeInformationReceived(const QString &sender, const QString &aircraft, const QString &airline, const QString &livery);
|
|
void customPilotPacketReceived(const QString &sender, const QStringList &data);
|
|
void interimPilotDataUpdatedReceived(const BlackMisc::Aviation::CAircraftSituation &situation);
|
|
void visualPilotDataUpdateReceived(const BlackMisc::Aviation::CAircraftSituation &situation);
|
|
void euroscopeSimDataUpdatedReceived(const BlackMisc::Aviation::CAircraftSituation &situation, const BlackMisc::Aviation::CAircraftParts &parts, qint64 currentOffsetTimeMs, const QString &model, const QString &livery);
|
|
void rawFsdMessage(const BlackMisc::Network::CRawFsdMessage &rawFsdMessage);
|
|
void planeInformationFsinnReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &airlineIcaoDesignator, const QString &aircraftDesignator, const QString &combinedAircraftType, const QString &modelString);
|
|
void revbAircraftConfigReceived(const QString &sender, const QString &config, qint64 currentOffsetTimeMs);
|
|
|
|
//! @}
|
|
|
|
//! We received a reply to one of our ATIS queries.
|
|
void atisReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CInformationMessage &atis);
|
|
|
|
//! We received a reply to one of our ATIS queries, containing the controller's planned logoff time.
|
|
void atisLogoffTimeReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &zuluTime);
|
|
|
|
//! We have sent a text message.
|
|
void textMessageSent(const BlackMisc::Network::CTextMessage &sentMessage);
|
|
|
|
//! Connection status has been changed
|
|
void connectionStatusChanged(BlackMisc::Network::CConnectionStatus oldStatus, BlackMisc::Network::CConnectionStatus newStatus);
|
|
|
|
//! Network error
|
|
void severeNetworkError(const QString &errorMessage);
|
|
|
|
//! Kill request (aka kicked)
|
|
void killRequestReceived(const QString &reason);
|
|
|
|
private:
|
|
//! \cond
|
|
friend BlackFsdTest::CTestFSDClient;
|
|
//! \endcond
|
|
|
|
//! Convenience functions for sendClientQuery
|
|
//! \remark really private, ONLY used by UNIT test, not CAirspaceMonitor
|
|
//! @{
|
|
void sendLogin(const QString &token = {});
|
|
void sendDeletePilot();
|
|
void sendDeleteAtc();
|
|
void sendPilotDataUpdate();
|
|
void sendInterimPilotDataUpdate();
|
|
void sendVisualPilotDataUpdate(bool slowUpdate = false);
|
|
void sendAtcDataUpdate(double latitude, double longitude);
|
|
void sendPing(const QString &receiver);
|
|
//
|
|
void sendClientQueryIsValidAtc(const BlackMisc::Aviation::CCallsign &callsign);
|
|
void sendClientQuery(ClientQueryType queryType, const BlackMisc::Aviation::CCallsign &receiver, const QStringList &queryData = {});
|
|
void sendTextMessage(const QString &receiver, const QString &message);
|
|
void sendPlaneInformation(const QString &receiver, const QString &aircraft, const QString &airline = {}, const QString &livery = {});
|
|
void sendPlaneInformationFsinn(const BlackMisc::Aviation::CCallsign &callsign);
|
|
void sendAircraftConfiguration(const QString &receiver, const QString &aircraftConfigJson);
|
|
//
|
|
void sendMessageString(const QString &message);
|
|
void sendQueuedMessage();
|
|
//! @}
|
|
|
|
//! Increase the statistics value for given identifier
|
|
//! @{
|
|
int increaseStatisticsValue(const QString &identifier, const QString &appendix = {});
|
|
int increaseStatisticsValue(const QString &identifier, int value);
|
|
//! @}
|
|
|
|
//! Message send to FSD
|
|
template <class T>
|
|
void sendQueudedMessage(const T &message)
|
|
{
|
|
if (!message.isValid()) { return; }
|
|
if (m_unitTestMode)
|
|
{
|
|
this->sendDirectMessage(message);
|
|
return;
|
|
}
|
|
m_queuedFsdMessages.enqueue(messageToFSDString(message));
|
|
}
|
|
|
|
//! Message send to FSD
|
|
template <class T>
|
|
void sendDirectMessage(const T &message)
|
|
{
|
|
if (!message.isValid()) { return; }
|
|
this->sendMessageString(messageToFSDString(message));
|
|
}
|
|
|
|
//! Unit test/debug functions
|
|
//! @{
|
|
void sendFsdMessage(const QString &message);
|
|
void setUnitTestMode(bool on) { m_unitTestMode = on; }
|
|
//! @}
|
|
|
|
//! Default model string
|
|
static const QString &defaultModelString()
|
|
{
|
|
static const QString dm("Cessna Skyhawk 172SP");
|
|
return dm;
|
|
}
|
|
|
|
//! Send if no model string is available
|
|
static const QString &noModelString()
|
|
{
|
|
static const QString noms("swift empty string");
|
|
return noms;
|
|
}
|
|
|
|
//! Model string as configured, also dependent from simulator
|
|
QString getConfiguredModelString(const BlackMisc::Simulation::CSimulatedAircraft &myAircraft) const;
|
|
|
|
//! Livery string, also dependent from simulator
|
|
QString getConfiguredLiveryString(const BlackMisc::Simulation::CSimulatedAircraft &myAircraft) const;
|
|
|
|
//! JSON packets
|
|
struct JsonPackets
|
|
{
|
|
static const QJsonObject &aircraftConfigRequest();
|
|
};
|
|
|
|
void sendAuthChallenge(const QString &challenge);
|
|
void sendAuthResponse(const QString &response);
|
|
void sendPong(const QString &receiver, const QString ×tamp);
|
|
void sendClientResponse(ClientQueryType queryType, const QString &receiver);
|
|
void sendClientIdentification(const QString &fsdChallenge);
|
|
void sendIncrementalAircraftConfig();
|
|
|
|
void readDataFromSocket() { this->readDataFromSocketMaxLines(); }
|
|
void readDataFromSocketMaxLines(int maxLines = -1);
|
|
void parseMessage(const QString &lineRaw);
|
|
|
|
QString socketErrorString(QAbstractSocket::SocketError error) const;
|
|
static QString socketErrorToQString(QAbstractSocket::SocketError error);
|
|
|
|
//! Init. the message types
|
|
void initializeMessageTypes();
|
|
|
|
// Type to string
|
|
const QString &messageTypeToString(MessageType mt) const;
|
|
|
|
//! Handle response tokens
|
|
//! @{
|
|
void handleAtcDataUpdate(const QStringList &tokens);
|
|
void handleAuthChallenge(const QStringList &tokens);
|
|
void handleAuthResponse(const QStringList &tokens);
|
|
void handleDeleteATC(const QStringList &tokens);
|
|
void handleDeletePilot(const QStringList &tokens);
|
|
void handleTextMessage(const QStringList &tokens);
|
|
void handlePilotDataUpdate(const QStringList &tokens);
|
|
void handleVisualPilotDataUpdate(const QStringList &tokens, MessageType messageType);
|
|
void handleVisualPilotDataToggle(const QStringList &tokens);
|
|
void handleEuroscopeSimData(const QStringList &tokens);
|
|
void handlePing(const QStringList &tokens);
|
|
void handlePong(const QStringList &tokens);
|
|
void handleKillRequest(const QStringList &tokens);
|
|
void handleFlightPlan(const QStringList &tokens);
|
|
void handleClientQuery(const QStringList &tokens);
|
|
void handleClientReponse(const QStringList &tokens);
|
|
void handleServerError(const QStringList &tokens);
|
|
void handleCustomPilotPacket(const QStringList &tokens);
|
|
void handleFsdIdentification(const QStringList &tokens);
|
|
void handleRevBClientPartsPacket(const QStringList &tokens);
|
|
void handleRehost(const QStringList &tokens);
|
|
|
|
//
|
|
void handleUnknownPacket(const QString &line);
|
|
void handleUnknownPacket(const QStringList &tokens);
|
|
//! @}
|
|
|
|
void printSocketError(QAbstractSocket::SocketError socketError);
|
|
void handleSocketError(QAbstractSocket::SocketError socketError);
|
|
void handleSocketConnected();
|
|
|
|
void updateConnectionStatus(BlackMisc::Network::CConnectionStatus newStatus);
|
|
|
|
//! Consolidate text messages if we receive multiple messages which belong together
|
|
//! \remark causes a slight delay
|
|
void consolidateTextMessage(const BlackMisc::Network::CTextMessage &textMessage);
|
|
|
|
//! Send the consolidatedTextMessages
|
|
void emitConsolidatedTextMessages();
|
|
|
|
//! Remember when last position was received
|
|
qint64 receivedPositionFixTsAndGetOffsetTime(const BlackMisc::Aviation::CCallsign &callsign, qint64 markerTs = -1);
|
|
|
|
//! Current offset time
|
|
qint64 currentOffsetTime(const BlackMisc::Aviation::CCallsign &callsign) const;
|
|
|
|
//! Clear state when connection is terminated
|
|
void clearState();
|
|
|
|
//! Clear state for callsign
|
|
void clearState(const BlackMisc::Aviation::CCallsign &callsign);
|
|
|
|
//! Insert as first value
|
|
void insertLatestOffsetTime(const BlackMisc::Aviation::CCallsign &callsign, qint64 offsetMs);
|
|
|
|
//! Average offset time in ms
|
|
qint64 averageOffsetTimeMs(const BlackMisc::Aviation::CCallsign &callsign, int &count, int maxLastValues = MaxOffseTimes) const;
|
|
|
|
//! Average offset time in ms
|
|
qint64 averageOffsetTimeMs(const BlackMisc::Aviation::CCallsign &callsign, int maxLastValues = MaxOffseTimes) const;
|
|
|
|
bool isInterimPositionSendingEnabledForServer() const;
|
|
bool isInterimPositionReceivingEnabledForServer() const;
|
|
bool isVisualPositionSendingEnabledForServer() const;
|
|
const BlackMisc::Network::CFsdSetup &getSetupForServer() const;
|
|
|
|
//! Handles ATIS replies from non-VATSIM servers. If the conditions are not met,
|
|
//! the message is released as normal text message.
|
|
void maybeHandleAtisReply(const BlackMisc::Aviation::CCallsign &sender, const BlackMisc::Aviation::CCallsign &receiver, const QString &message);
|
|
|
|
//! Settings have been changed
|
|
void fsdMessageSettingsChanged();
|
|
|
|
//! Emit raw FSD message (mostly for debugging)
|
|
void emitRawFsdMessage(const QString &fsdMessage, bool isSent);
|
|
|
|
//! Save the statistics
|
|
bool saveNetworkStatistics(const QString &server);
|
|
|
|
//! Timers
|
|
//! @{
|
|
void startPositionTimers();
|
|
void stopPositionTimers();
|
|
//! @}
|
|
|
|
//! Update the ATIS map
|
|
void updateAtisMap(const QString &callsign, AtisLineType type, const QString &line);
|
|
|
|
//! Check if there is a pending logon attempt which "hangs"
|
|
void pendingTimeoutCheck();
|
|
|
|
//! Fix ATC station range
|
|
static const BlackMisc::PhysicalQuantities::CLength &fixAtcRange(const BlackMisc::PhysicalQuantities::CLength &networkRange, const BlackMisc::Aviation::CCallsign &cs);
|
|
|
|
//! Max or 1st non-null value
|
|
static const BlackMisc::PhysicalQuantities::CLength &maxOrNotNull(const BlackMisc::PhysicalQuantities::CLength &l1, const BlackMisc::PhysicalQuantities::CLength &l2);
|
|
|
|
//! String withou colons
|
|
static QString noColons(const QString &input);
|
|
|
|
//! Get a short-lived, one-time-use token from Vatsim web service, to avoid sending plaintext password to FSD
|
|
void getVatsimAuthToken(const QString &cid, const QString &password, const BlackMisc::CSlot<void(const QString &)> &callback);
|
|
|
|
//! Convert FlightRules to FlightType
|
|
static FlightType getFlightType(BlackMisc::Aviation::CFlightPlan::FlightRules flightRule);
|
|
|
|
vatsim_auth *m_clientAuth = nullptr;
|
|
vatsim_auth *m_serverAuth = nullptr;
|
|
QString m_lastServerAuthChallenge;
|
|
qint64 m_loginSince = -1; //!< when login was triggered
|
|
static constexpr qint64 PendingConnectionTimeoutMs = 7500;
|
|
|
|
// Parser
|
|
QHash<QString, MessageType> m_messageTypeMapping;
|
|
|
|
std::unique_ptr<QTcpSocket> m_socket = std::make_unique<QTcpSocket>(this); //!< used TCP socket, parent needed as it runs in worker thread
|
|
void connectSocketSignals();
|
|
bool m_rehosting = false;
|
|
|
|
std::atomic_bool m_unitTestMode { false };
|
|
std::atomic_bool m_printToConsole { false };
|
|
|
|
BlackMisc::Network::CConnectionStatus m_connectionStatus;
|
|
mutable QReadWriteLock m_lockConnectionStatus { QReadWriteLock::Recursive };
|
|
|
|
BlackMisc::Aviation::CAircraftParts m_sentAircraftConfig; //!< aircraft parts sent
|
|
BlackMisc::CTokenBucket m_tokenBucket; //!< used with aircraft parts messages
|
|
BlackMisc::Aviation::CCallsignSet m_interimPositionReceivers; //!< all aircraft receiving interim positions
|
|
BlackMisc::Network::CTextMessageList m_textMessagesToConsolidate; //!< waiting for new messages
|
|
BlackMisc::CDigestSignal m_dsSendTextMessage { this, &CFSDClient::emitConsolidatedTextMessages, 250, 10 };
|
|
|
|
//! ATIS message
|
|
struct AtisMessage
|
|
{
|
|
QString voiceRoom;
|
|
QStringList textLines;
|
|
QString zuluLogoff;
|
|
int lineCount = 0;
|
|
};
|
|
|
|
QMap<QString, AtisMessage> m_mapAtisMessages;
|
|
|
|
//! Pending ATIS query since
|
|
struct PendingAtisQuery
|
|
{
|
|
QDateTime m_queryTime = QDateTime::currentDateTimeUtc();
|
|
QStringList m_atisMessage;
|
|
};
|
|
|
|
QHash<BlackMisc::Aviation::CCallsign, PendingAtisQuery> m_pendingAtisQueries;
|
|
QHash<BlackMisc::Aviation::CCallsign, qint64> m_lastPositionUpdate;
|
|
QHash<BlackMisc::Aviation::CCallsign, QList<qint64>> m_lastOffsetTimes; //!< latest offset first
|
|
QHash<BlackMisc::Aviation::CCallsign, qint64> m_interpolatedOffsetTime;
|
|
static const int c_offsetTimeInterpolationInverseRate = 4;
|
|
|
|
BlackMisc::Aviation::CAtcStationList m_atcStations;
|
|
|
|
BlackMisc::CSettingReadOnly<BlackCore::Vatsim::TRawFsdMessageSetting> m_fsdMessageSetting { this, &CFSDClient::fsdMessageSettingsChanged };
|
|
QFile m_rawFsdMessageLogFile;
|
|
std::atomic_bool m_rawFsdMessagesEnabled { false };
|
|
std::atomic_bool m_filterPasswordFromLogin { false };
|
|
|
|
// timer parents are needed as we move to thread
|
|
QTimer m_scheduledConfigUpdate { this }; //!< config updates
|
|
QTimer m_positionUpdateTimer { this }; //!< sending positions
|
|
QTimer m_interimPositionUpdateTimer { this }; //!< sending interim positions
|
|
QTimer m_visualPositionUpdateTimer { this }; //!< sending visual positions
|
|
QTimer m_fsdSendMessageTimer { this }; //!< FSD message sending
|
|
|
|
qint64 m_additionalOffsetTime = 0; //!< additional offset time
|
|
|
|
std::atomic_bool m_statistics { false };
|
|
QMap <QString, int> m_callStatistics; //!< how many calls?
|
|
QVector <QPair<qint64, QString>> m_callByTime; //!< "last call vs. ms"
|
|
mutable QReadWriteLock m_lockStatistics { QReadWriteLock::Recursive }; //!< for user, client and buffered data
|
|
|
|
// User data
|
|
BlackMisc::Network::CServer m_server;
|
|
BlackMisc::Network::CLoginMode m_loginMode;
|
|
QTextCodec *m_fsdTextCodec = nullptr;
|
|
SimType m_simType = SimType::Unknown;
|
|
PilotRating m_pilotRating = PilotRating::Unknown;
|
|
AtcRating m_atcRating = AtcRating::Unknown;
|
|
BlackMisc::Simulation::CSimulatorInfo m_simTypeInfo; // same as m_simType
|
|
|
|
// Client data
|
|
QString m_clientName;
|
|
QString m_hostApplication;
|
|
int m_versionMajor = 0;
|
|
int m_versionMinor = 0;
|
|
int m_protocolRevision = 0;
|
|
ServerType m_serverType = ServerType::LegacyFsd;
|
|
Capabilities m_capabilities = Capabilities::None;
|
|
|
|
// buffered data for FSD
|
|
BlackMisc::Aviation::CCallsign m_ownCallsign; //!< "buffered callsign", as this must not change when connected
|
|
BlackMisc::Aviation::CCallsign m_partnerCallsign; //!< "buffered"callsign", of partner flying in shared cockpit
|
|
BlackMisc::Aviation::CAircraftIcaoCode m_ownAircraftIcaoCode; //!< "buffered icao", as this must not change when connected
|
|
BlackMisc::Aviation::CAirlineIcaoCode m_ownAirlineIcaoCode; //!< "buffered icao", as this must not change when connected
|
|
QString m_ownLivery; //!< "buffered livery", as this must not change when connected
|
|
QString m_ownModelString; //!< "buffered model string", as this must not change when connected
|
|
std::atomic_bool m_sendLiveryString { true };
|
|
std::atomic_bool m_sendModelString { true };
|
|
|
|
mutable QReadWriteLock m_lockUserClientBuffered { QReadWriteLock::Recursive }; //!< for user, client and buffered data
|
|
QString getOwnCallsignAsString() const { QReadLocker l(&m_lockUserClientBuffered); return m_ownCallsign.asString(); }
|
|
|
|
QQueue<QString> m_queuedFsdMessages;
|
|
|
|
//! An illegal FSD state has been detected
|
|
void handleIllegalFsdState(const QString &message);
|
|
|
|
static const int MaxOffseTimes = 6; //!< Max offset times kept
|
|
static int constexpr c_processingIntervalMsec = 100; //!< interval for the processing timer
|
|
static int constexpr c_updatePostionIntervalMsec = 5000; //!< interval for the position update timer (send our position to network)
|
|
static int constexpr c_updateInterimPostionIntervalMsec = 1000; //!< interval for iterim position updates (send our position as interim position)
|
|
static int constexpr c_updateVisualPositionIntervalMsec = 200; //!< interval for the VATSIM visual position updates (send our position and 6DOF velocity)
|
|
static int constexpr c_sendFsdMsgIntervalMsec = 10; //!< interval for FSD send messages
|
|
bool m_stoppedSendingVisualPositions = false; //!< for when velocity drops to zero
|
|
bool m_serverWantsVisualPositions = false; //!< there are interested clients in range
|
|
unsigned m_visualPositionUpdateSentCount = 0; //!< for choosing when to send a periodic (slowfast) packet
|
|
};
|
|
} // ns
|
|
|
|
#endif
|