6 #ifndef SWIFT_CORE_FSD_CLIENT_H
7 #define SWIFT_CORE_FSD_CLIENT_H
29 #include "misc/tokenbucket.h"
32 #ifdef SWIFT_VATSIM_SUPPORT
33 # include "vatsim/vatsimauth.h"
38 #include <QCommandLineOption>
42 #include <QReadWriteLock>
58 namespace SwiftFsdTest
62 namespace swift::core::fsd
91 static const QStringList &getLogCategories();
104 QWriteLocker l(&m_lockUserClientBuffered);
105 m_clientName = clientName;
109 QWriteLocker l(&m_lockUserClientBuffered);
110 m_hostApplication = hostApplication;
114 QWriteLocker l(&m_lockUserClientBuffered);
115 m_versionMajor = major;
116 m_versionMinor = minor;
119 #ifdef SWIFT_VATSIM_SUPPORT
120 void setClientIdAndKey(quint16
id,
const QByteArray &key);
125 QWriteLocker l(&m_lockUserClientBuffered);
126 m_capabilities = capabilities;
131 QWriteLocker l(&m_lockUserClientBuffered);
137 QWriteLocker l(&m_lockUserClientBuffered);
138 m_partnerCallsign = callsign;
141 void setLiveryAndModelString(
const QString &livery,
bool sendLiveryString,
const QString &modelString,
142 bool sendModelString);
144 void setSimType(swift::misc::simulation::CSimulatorInfo::Simulator simulator);
147 QWriteLocker l(&m_lockUserClientBuffered);
148 m_pilotRating = rating;
152 QWriteLocker l(&m_lockUserClientBuffered);
153 m_atcRating = rating;
163 QReadLocker l(&m_lockUserClientBuffered);
169 QStringList getPresetValues()
const;
175 QReadLocker l(&m_lockUserClientBuffered);
176 return m_ownCallsign;
183 QReadLocker l(&m_lockUserClientBuffered);
184 return m_partnerCallsign;
191 QReadLocker l(&m_lockUserClientBuffered);
199 QReadLocker l(&m_lockUserClientBuffered);
200 return m_pilotRating;
205 void connectToServer();
206 void disconnectFromServer();
213 m_interimPositionReceivers.push_back(receiver);
217 m_interimPositionReceivers.remove(receiver);
235 void sendRadioMessage(
const QVector<int> &frequencieskHz,
const QString &message);
251 QReadLocker l(&m_lockConnectionStatus);
252 return m_connectionStatus;
254 bool isConnected()
const {
return this->getConnectionStatus().isConnected(); }
255 bool isDisconnected()
const {
return this->getConnectionStatus().isDisconnected(); }
256 bool isPendingConnection()
const;
263 m_statistics = enabled;
270 void clearStatistics();
273 QString getNetworkStatisticsAsText(
bool reset,
const QString &separator =
"\n");
279 void gracefulShutdown();
299 swift::misc::network::CClient::Capabilities capabilities);
305 const QString &livery);
311 qint64 currentOffsetTimeMs,
const QString &model,
const QString &livery);
314 const QString &airlineIcaoDesignator,
const QString &aircraftDesignator,
315 const QString &combinedAircraftType,
const QString &modelString);
349 void sendLogin(
const QString &token = {});
350 void sendDeletePilot();
351 void sendDeleteAtc();
352 void sendPilotDataUpdate();
353 void sendInterimPilotDataUpdate();
354 void sendVisualPilotDataUpdate(
bool slowUpdate =
false);
355 void sendAtcDataUpdate(
double latitude,
double longitude);
356 void sendPing(
const QString &receiver);
360 const QStringList &queryData = {});
361 void sendTextMessage(
const QString &receiver,
const QString &message);
362 void sendPlaneInformation(
const QString &receiver,
const QString &aircraft,
const QString &airline = {},
363 const QString &livery = {});
365 void sendAircraftConfiguration(
const QString &receiver,
const QString &aircraftConfigJson);
367 void sendMessageString(
const QString &message);
368 void sendQueuedMessage();
373 int increaseStatisticsValue(
const QString &identifier,
const QString &appendix = {});
374 int increaseStatisticsValue(
const QString &identifier,
int value);
379 void sendQueuedMessage(
const T &message)
381 if (!message.isValid()) {
return; }
384 this->sendDirectMessage(message);
392 void sendDirectMessage(
const T &message)
394 if (!message.isValid()) {
return; }
400 void sendFsdMessage(
const QString &message);
401 void setUnitTestMode(
bool on) { m_unitTestMode = on; }
405 static const QString &defaultModelString()
407 static const QString dm(
"Cessna Skyhawk 172SP");
412 static const QString &noModelString()
414 static const QString noms(
"swift empty string");
427 static const QJsonObject &aircraftConfigRequest();
430 void sendAuthChallenge(
const QString &challenge);
431 void sendAuthResponse(
const QString &response);
432 void sendPong(
const QString &receiver,
const QString ×tamp);
433 void sendClientResponse(ClientQueryType queryType,
const QString &receiver);
434 #ifdef SWIFT_VATSIM_SUPPORT
435 void sendClientIdentification(
const QString &fsdChallenge);
437 void sendIncrementalAircraftConfig();
439 void readDataFromSocket() { this->readDataFromSocketMaxLines(); }
440 void readDataFromSocketMaxLines(
int maxLines = -1);
441 void parseMessage(
const QString &lineRaw);
443 QString socketErrorString(QAbstractSocket::SocketError error)
const;
444 static QString socketErrorToQString(QAbstractSocket::SocketError error);
447 void initializeMessageTypes();
450 const QString &messageTypeToString(
MessageType mt)
const;
454 void handleAtcDataUpdate(
const QStringList &tokens);
455 #ifdef SWIFT_VATSIM_SUPPORT
456 void handleAuthChallenge(
const QStringList &tokens);
457 void handleAuthResponse(
const QStringList &tokens);
459 void handleDeleteATC(
const QStringList &tokens);
460 void handleDeletePilot(
const QStringList &tokens);
461 void handleTextMessage(
const QStringList &tokens);
462 void handlePilotDataUpdate(
const QStringList &tokens);
463 void handleVisualPilotDataUpdate(
const QStringList &tokens,
MessageType messageType);
464 void handleVisualPilotDataToggle(
const QStringList &tokens);
465 void handleEuroscopeSimData(
const QStringList &tokens);
466 void handlePing(
const QStringList &tokens);
467 void handlePong(
const QStringList &tokens);
468 void handleKillRequest(
const QStringList &tokens);
469 void handleFlightPlan(
const QStringList &tokens);
470 void handleClientQuery(
const QStringList &tokens);
471 void handleClientResponse(
const QStringList &tokens);
472 void handleServerError(
const QStringList &tokens);
473 void handleCustomPilotPacket(
const QStringList &tokens);
474 #ifdef SWIFT_VATSIM_SUPPORT
475 void handleFsdIdentification(
const QStringList &tokens);
477 void handleRevBClientPartsPacket(
const QStringList &tokens);
478 void handleRehost(
const QStringList &tokens);
479 void handleMute(
const QStringList &tokens);
482 void handleUnknownPacket(
const QString &line);
483 void handleUnknownPacket(
const QStringList &tokens);
486 void printSocketError(QAbstractSocket::SocketError socketError);
487 void handleSocketError(QAbstractSocket::SocketError socketError);
488 void handleSocketConnected();
497 void emitConsolidatedTextMessages();
501 qint64 markerTs = -1);
517 int maxLastValues = c_maxOffsetTimes)
const;
519 bool isInterimPositionSendingEnabledForServer()
const;
520 bool isInterimPositionReceivingEnabledForServer()
const;
521 bool isVisualPositionSendingEnabledForServer()
const;
530 void fsdMessageSettingsChanged();
533 void emitRawFsdMessage(
const QString &fsdMessage,
bool isSent);
536 bool saveNetworkStatistics(
const QString &server);
540 void startPositionTimers();
541 void stopPositionTimers();
545 void updateAtisMap(
const QString &callsign, AtisLineType type,
const QString &line);
548 void pendingTimeoutCheck();
561 static QString noColons(
const QString &input);
564 void getVatsimAuthToken(
const QString &cid,
const QString &password,
570 #ifdef SWIFT_VATSIM_SUPPORT
571 vatsim_auth *m_clientAuth =
nullptr;
572 vatsim_auth *m_serverAuth =
nullptr;
574 QString m_lastServerAuthChallenge;
575 qint64 m_loginSince = -1;
576 static constexpr qint64 PendingConnectionTimeoutMs = 7500;
581 std::shared_ptr<QTcpSocket> m_socket =
582 std::make_shared<QTcpSocket>(
this);
583 void connectSocketSignals();
584 void initiateConnection(std::shared_ptr<QTcpSocket> rehostingSocket = {},
const QString &rehostingHost = {});
585 void resolveLoadBalancing(
const QString &host, std::function<
void(
const QString &)> callback);
586 bool m_rehosting =
false;
588 std::atomic_bool m_unitTestMode {
false };
589 std::atomic_bool m_printToConsole {
false };
592 mutable QReadWriteLock m_lockConnectionStatus { QReadWriteLock::Recursive };
598 misc::CDigestSignal m_dsSendTextMessage {
this, &CFSDClient::emitConsolidatedTextMessages,
599 std::chrono::milliseconds(250), 10 };
605 QStringList m_textLines;
606 QString m_zuluLogoff;
613 struct PendingAtisQuery
615 QDateTime m_queryTime = QDateTime::currentDateTimeUtc();
616 QStringList m_atisMessage;
626 this, &CFSDClient::fsdMessageSettingsChanged
628 QFile m_rawFsdMessageLogFile;
629 std::atomic_bool m_rawFsdMessagesEnabled {
false };
630 std::atomic_bool m_filterPasswordFromLogin {
false };
633 QTimer m_scheduledConfigUpdate {
this };
634 QTimer m_positionUpdateTimer {
this };
635 QTimer m_interimPositionUpdateTimer {
this };
636 QTimer m_visualPositionUpdateTimer {
this };
637 QTimer m_fsdSendMessageTimer {
this };
639 qint64 m_additionalOffsetTime = 0;
641 std::atomic_bool m_statistics {
false };
643 QVector<QPair<qint64, QString>> m_callByTime;
644 mutable QReadWriteLock m_lockStatistics { QReadWriteLock::Recursive };
649 QStringEncoder m_encoder;
650 QStringDecoder m_decoder;
651 SimType m_simType = SimType::Unknown;
653 AtcRating m_atcRating = AtcRating::Unknown;
657 QString m_clientName;
658 QString m_hostApplication;
659 int m_versionMajor = 0;
660 int m_versionMinor = 0;
661 int m_protocolRevision = 0;
662 ServerType m_serverType = ServerType::LegacyFsd;
670 m_ownAircraftIcaoCode;
672 m_ownAirlineIcaoCode;
674 QString m_ownModelString;
675 std::atomic_bool m_sendLiveryString {
true };
676 std::atomic_bool m_sendModelString {
true };
678 mutable QReadWriteLock m_lockUserClientBuffered {
679 QReadWriteLock::Recursive
681 QString getOwnCallsignAsString()
const
683 QReadLocker l(&m_lockUserClientBuffered);
687 QQueue<QString> m_queuedFsdMessages;
690 void handleIllegalFsdState(
const QString &message);
692 static int constexpr c_maxOffsetTimes = 6;
693 static int constexpr c_processingIntervalMsec = 100;
694 static int constexpr c_updatePositionIntervalMsec =
696 static int constexpr c_updateInterimPositionIntervalMsec =
698 static int constexpr c_updateVisualPositionIntervalMsec =
700 static int constexpr c_sendFsdMsgIntervalMsec = 10;
701 bool m_stoppedSendingVisualPositions =
false;
702 bool m_serverWantsVisualPositions =
false;
703 unsigned m_visualPositionUpdateSentCount = 0;
FSD client Todo: Send (interim) data updates automatically Todo Check ':' in FSD messages....
void customPilotPacketReceived(const QString &sender, const QStringList &data)
Client responses received.
swift::misc::aviation::CCallsign getPresetPartnerCallsign() const
Partner callsign if any.
void planeInformationReceived(const QString &sender, const QString &aircraft, const QString &airline, const QString &livery)
Client responses received.
void flightPlanReceived(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CFlightPlan &flightPlan)
Client responses received.
void rawFsdMessage(const swift::misc::network::CRawFsdMessage &rawFsdMessage)
Client responses received.
void textMessagesReceived(const swift::misc::network::CTextMessageList &messages)
Client responses received.
bool isConnected() const
Connection status.
void muteRequestReceived(bool mute)
Client responses received.
void atcDataUpdateReceived(const swift::misc::aviation::CCallsign &callsign, const swift::misc::physical_quantities::CFrequency &freq, const swift::misc::geo::CCoordinateGeodetic &pos, const swift::misc::physical_quantities::CLength &range)
Client responses received.
void setAtcRating(AtcRating rating)
Preset functions.
swift::misc::aviation::CCallsign getPresetCallsign() const
Callsign if any.
bool isStatisticsEnabled() const
Statistics enable functions.
void realNameResponseReceived(const QString &sender, const QString &realName)
Client responses received.
void setLoginMode(const swift::misc::network::CLoginMode &mode)
Preset functions.
void connectionStatusChanged(swift::misc::network::CConnectionStatus oldStatus, swift::misc::network::CConnectionStatus newStatus)
Connection status has been changed.
void setClientName(const QString &clientName)
Preset functions.
void interimPilotDataUpdatedReceived(const swift::misc::aviation::CAircraftSituation &situation)
Client responses received.
void planeInformationFsinnReceived(const swift::misc::aviation::CCallsign &callsign, const QString &airlineIcaoDesignator, const QString &aircraftDesignator, const QString &combinedAircraftType, const QString &modelString)
Client responses received.
void capabilityResponseReceived(const swift::misc::aviation::CCallsign &sender, swift::misc::network::CClient::Capabilities capabilities)
Client responses received.
void revbAircraftConfigReceived(const QString &sender, const QString &config, qint64 currentOffsetTimeMs)
Client responses received.
void setClientCapabilities(Capabilities capabilities)
Preset functions.
void setPartnerCallsign(const swift::misc::aviation::CCallsign &callsign)
Preset functions.
void pongReceived(const QString &sender, double elapsedTimeMs)
Client responses received.
const swift::misc::network::CServer & getServer() const
Get the server.
swift::misc::network::CLoginMode getLoginMode() const
Mode.
void printToConsole(bool on)
Debugging and UNIT tests.
void validAtcResponseReceived(const QString &callsign, bool isValidAtc)
Client responses received.
bool setStatisticsEnable(bool enabled)
Statistics enable functions.
void atisReplyReceived(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CInformationMessage &atis)
We received a reply to one of our ATIS queries.
void visualPilotDataUpdateReceived(const swift::misc::aviation::CAircraftSituation &situation)
Client responses received.
void deleteAtcReceived(const QString &cid)
Client responses received.
PilotRating getPilotRating() const
Rating.
void addInterimPositionReceiver(const swift::misc::aviation::CCallsign &receiver)
Interim positions.
void com1FrequencyResponseReceived(const QString &sender, const swift::misc::physical_quantities::CFrequency &frequency)
Client responses received.
void setHostApplication(const QString &hostApplication)
Preset functions.
void setPilotRating(PilotRating rating)
Preset functions.
void removeInterimPositionReceiver(const swift::misc::aviation::CCallsign &receiver)
Interim positions.
void aircraftConfigReceived(const QString &sender, const QJsonObject &config, qint64 currentOffsetTimeMs)
Client responses received.
void pilotDataUpdateReceived(const swift::misc::aviation::CAircraftSituation &situation, const swift::misc::aviation::CTransponder &transponder)
Client responses received.
void textMessageSent(const swift::misc::network::CTextMessage &sentMessage)
We have sent a text message.
void atisLogoffTimeReplyReceived(const swift::misc::aviation::CCallsign &callsign, const QString &zuluTime)
We received a reply to one of our ATIS queries, containing the controller's planned logoff time.
void killRequestReceived(const QString &reason)
Kill request (aka kicked)
void setVersion(int major, int minor)
Preset functions.
void deletePilotReceived(const QString &cid)
Client responses received.
swift::misc::network::CConnectionStatus getConnectionStatus() const
Connection status.
void euroscopeSimDataUpdatedReceived(const swift::misc::aviation::CAircraftSituation &situation, const swift::misc::aviation::CAircraftParts &parts, qint64 currentOffsetTimeMs, const QString &model, const QString &livery)
Client responses received.
bool isDisconnected() const
Connection status.
void serverResponseReceived(const QString &sender, const QString &hostName)
Client responses received.
void severeNetworkError(const QString &errorMessage)
Network error.
Base class for a long-lived worker object which lives in its own thread.
Callable wrapper for a member function with function signature F.
Value object for ICAO classification.
Value object encapsulating information of aircraft's parts.
Value object encapsulating information of an aircraft's situation.
Value object for ICAO classification.
Value object for a list of ATC stations.
Value object encapsulating information of a callsign.
const QString & asString() const
Get callsign (normalized)
Value object for a set of callsigns.
Value object for a flight plan.
FlightRules
Flight rules (VFR or IFR)
Class which can be directly used to access an.
Value object encapsulating information about a connection status.
Value object for a FSD setup.
Value object encapsulating information about login mode.
Value object for a raw FSD message.
Value object encapsulating information of a server.
Value object encapsulating information of a text message.
Value object encapsulating a list of text messages.
Direct in memory access to client (network client) data.
Direct threadsafe in memory access to current ecosystem.
Physical unit length (length)
Delegating class which can be directly used to access an.
Class which can be directly used to access an.
Comprehensive information of an aircraft.
Class which can be directly used to access an.
Simple hardcoded info about the corresponding simulator.
Direct threadsafe in memory access to own aircraft.
Direct thread safe in memory access to remote aircraft.
ServerType
FSD Server type.
SimType
Flight simulator type.
PilotRating
Pilot ratings.
ClientQueryType
Client query types.
Capabilities
Client capability flags */.
TextMessageGroups
Message groups.
constexpr int PROTOCOL_REVISION_VATSIM_AUTH
Protocol version.
constexpr int PROTOCOL_REVISION_VATSIM_VELOCITY
Protocol version.
constexpr int PROTOCOL_REVISION_CLASSIC
Protocol version.
constexpr int PROTOCOL_REVISION_VATSIM_ATC
Protocol version.
QString messageToFSDString(const T &message)
String which will be send.
#define SWIFT_CORE_EXPORT
Export a class or function from the library.