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>
51 #define PROTOCOL_REVISION_CLASSIC 9
52 #define PROTOCOL_REVISION_VATSIM_ATC 10
53 #define PROTOCOL_REVISION_VATSIM_AUTH 100
54 #define PROTOCOL_REVISION_VATSIM_VELOCITY 101
59 namespace SwiftFsdTest
63 namespace swift::core::fsd
92 static const QStringList &getLogCategories();
105 QWriteLocker l(&m_lockUserClientBuffered);
106 m_clientName = clientName;
110 QWriteLocker l(&m_lockUserClientBuffered);
111 m_hostApplication = hostApplication;
115 QWriteLocker l(&m_lockUserClientBuffered);
116 m_versionMajor = major;
117 m_versionMinor = minor;
120 #ifdef SWIFT_VATSIM_SUPPORT
121 void setClientIdAndKey(quint16
id,
const QByteArray &key);
126 QWriteLocker l(&m_lockUserClientBuffered);
127 m_capabilities = capabilities;
132 QWriteLocker l(&m_lockUserClientBuffered);
138 QWriteLocker l(&m_lockUserClientBuffered);
139 m_partnerCallsign = callsign;
142 void setLiveryAndModelString(
const QString &livery,
bool sendLiveryString,
const QString &modelString,
143 bool sendModelString);
145 void setSimType(swift::misc::simulation::CSimulatorInfo::Simulator simulator);
148 QWriteLocker l(&m_lockUserClientBuffered);
149 m_pilotRating = rating;
153 QWriteLocker l(&m_lockUserClientBuffered);
154 m_atcRating = rating;
164 QReadLocker l(&m_lockUserClientBuffered);
170 QStringList getPresetValues()
const;
176 QReadLocker l(&m_lockUserClientBuffered);
177 return m_ownCallsign;
184 QReadLocker l(&m_lockUserClientBuffered);
185 return m_partnerCallsign;
192 QReadLocker l(&m_lockUserClientBuffered);
200 QReadLocker l(&m_lockUserClientBuffered);
201 return m_pilotRating;
206 void connectToServer();
207 void disconnectFromServer();
214 m_interimPositionReceivers.push_back(receiver);
218 m_interimPositionReceivers.remove(receiver);
236 void sendRadioMessage(
const QVector<int> &frequencieskHz,
const QString &message);
252 QReadLocker l(&m_lockConnectionStatus);
253 return m_connectionStatus;
255 bool isConnected()
const {
return this->getConnectionStatus().isConnected(); }
256 bool isDisconnected()
const {
return this->getConnectionStatus().isDisconnected(); }
257 bool isPendingConnection()
const;
264 m_statistics = enabled;
271 void clearStatistics();
274 QString getNetworkStatisticsAsText(
bool reset,
const QString &separator =
"\n");
280 void gracefulShutdown();
300 swift::misc::network::CClient::Capabilities capabilities);
306 const QString &livery);
312 qint64 currentOffsetTimeMs,
const QString &model,
const QString &livery);
315 const QString &airlineIcaoDesignator,
const QString &aircraftDesignator,
316 const QString &combinedAircraftType,
const QString &modelString);
350 void sendLogin(
const QString &token = {});
351 void sendDeletePilot();
352 void sendDeleteAtc();
353 void sendPilotDataUpdate();
354 void sendInterimPilotDataUpdate();
355 void sendVisualPilotDataUpdate(
bool slowUpdate =
false);
356 void sendAtcDataUpdate(
double latitude,
double longitude);
357 void sendPing(
const QString &receiver);
361 const QStringList &queryData = {});
362 void sendTextMessage(
const QString &receiver,
const QString &message);
363 void sendPlaneInformation(
const QString &receiver,
const QString &aircraft,
const QString &airline = {},
364 const QString &livery = {});
366 void sendAircraftConfiguration(
const QString &receiver,
const QString &aircraftConfigJson);
368 void sendMessageString(
const QString &message);
369 void sendQueuedMessage();
374 int increaseStatisticsValue(
const QString &identifier,
const QString &appendix = {});
375 int increaseStatisticsValue(
const QString &identifier,
int value);
380 void sendQueuedMessage(
const T &message)
382 if (!message.isValid()) {
return; }
385 this->sendDirectMessage(message);
393 void sendDirectMessage(
const T &message)
395 if (!message.isValid()) {
return; }
401 void sendFsdMessage(
const QString &message);
402 void setUnitTestMode(
bool on) { m_unitTestMode = on; }
406 static const QString &defaultModelString()
408 static const QString dm(
"Cessna Skyhawk 172SP");
413 static const QString &noModelString()
415 static const QString noms(
"swift empty string");
428 static const QJsonObject &aircraftConfigRequest();
431 void sendAuthChallenge(
const QString &challenge);
432 void sendAuthResponse(
const QString &response);
433 void sendPong(
const QString &receiver,
const QString ×tamp);
434 void sendClientResponse(ClientQueryType queryType,
const QString &receiver);
435 #ifdef SWIFT_VATSIM_SUPPORT
436 void sendClientIdentification(
const QString &fsdChallenge);
438 void sendIncrementalAircraftConfig();
440 void readDataFromSocket() { this->readDataFromSocketMaxLines(); }
441 void readDataFromSocketMaxLines(
int maxLines = -1);
442 void parseMessage(
const QString &lineRaw);
444 QString socketErrorString(QAbstractSocket::SocketError error)
const;
445 static QString socketErrorToQString(QAbstractSocket::SocketError error);
448 void initializeMessageTypes();
451 const QString &messageTypeToString(
MessageType mt)
const;
455 void handleAtcDataUpdate(
const QStringList &tokens);
456 #ifdef SWIFT_VATSIM_SUPPORT
457 void handleAuthChallenge(
const QStringList &tokens);
458 void handleAuthResponse(
const QStringList &tokens);
460 void handleDeleteATC(
const QStringList &tokens);
461 void handleDeletePilot(
const QStringList &tokens);
462 void handleTextMessage(
const QStringList &tokens);
463 void handlePilotDataUpdate(
const QStringList &tokens);
464 void handleVisualPilotDataUpdate(
const QStringList &tokens,
MessageType messageType);
465 void handleVisualPilotDataToggle(
const QStringList &tokens);
466 void handleEuroscopeSimData(
const QStringList &tokens);
467 void handlePing(
const QStringList &tokens);
468 void handlePong(
const QStringList &tokens);
469 void handleKillRequest(
const QStringList &tokens);
470 void handleFlightPlan(
const QStringList &tokens);
471 void handleClientQuery(
const QStringList &tokens);
472 void handleClientResponse(
const QStringList &tokens);
473 void handleServerError(
const QStringList &tokens);
474 void handleCustomPilotPacket(
const QStringList &tokens);
475 #ifdef SWIFT_VATSIM_SUPPORT
476 void handleFsdIdentification(
const QStringList &tokens);
478 void handleRevBClientPartsPacket(
const QStringList &tokens);
479 void handleRehost(
const QStringList &tokens);
480 void handleMute(
const QStringList &tokens);
483 void handleUnknownPacket(
const QString &line);
484 void handleUnknownPacket(
const QStringList &tokens);
487 void printSocketError(QAbstractSocket::SocketError socketError);
488 void handleSocketError(QAbstractSocket::SocketError socketError);
489 void handleSocketConnected();
498 void emitConsolidatedTextMessages();
502 qint64 markerTs = -1);
518 int maxLastValues = c_maxOffsetTimes)
const;
522 int maxLastValues = c_maxOffsetTimes)
const;
524 bool isInterimPositionSendingEnabledForServer()
const;
525 bool isInterimPositionReceivingEnabledForServer()
const;
526 bool isVisualPositionSendingEnabledForServer()
const;
535 void fsdMessageSettingsChanged();
538 void emitRawFsdMessage(
const QString &fsdMessage,
bool isSent);
541 bool saveNetworkStatistics(
const QString &server);
545 void startPositionTimers();
546 void stopPositionTimers();
550 void updateAtisMap(
const QString &callsign, AtisLineType type,
const QString &line);
553 void pendingTimeoutCheck();
566 static QString noColons(
const QString &input);
569 void getVatsimAuthToken(
const QString &cid,
const QString &password,
575 #ifdef SWIFT_VATSIM_SUPPORT
576 vatsim_auth *m_clientAuth =
nullptr;
577 vatsim_auth *m_serverAuth =
nullptr;
579 QString m_lastServerAuthChallenge;
580 qint64 m_loginSince = -1;
581 static constexpr qint64 PendingConnectionTimeoutMs = 7500;
586 std::shared_ptr<QTcpSocket> m_socket =
587 std::make_shared<QTcpSocket>(
this);
588 void connectSocketSignals();
589 void initiateConnection(std::shared_ptr<QTcpSocket> rehostingSocket = {},
const QString &rehostingHost = {});
590 void resolveLoadBalancing(
const QString &host, std::function<
void(
const QString &)> callback);
591 bool m_rehosting =
false;
593 std::atomic_bool m_unitTestMode {
false };
594 std::atomic_bool m_printToConsole {
false };
597 mutable QReadWriteLock m_lockConnectionStatus { QReadWriteLock::Recursive };
603 misc::CDigestSignal m_dsSendTextMessage {
this, &CFSDClient::emitConsolidatedTextMessages,
604 std::chrono::milliseconds(250), 10 };
610 QStringList textLines;
618 struct PendingAtisQuery
620 QDateTime m_queryTime = QDateTime::currentDateTimeUtc();
621 QStringList m_atisMessage;
631 this, &CFSDClient::fsdMessageSettingsChanged
633 QFile m_rawFsdMessageLogFile;
634 std::atomic_bool m_rawFsdMessagesEnabled {
false };
635 std::atomic_bool m_filterPasswordFromLogin {
false };
638 QTimer m_scheduledConfigUpdate {
this };
639 QTimer m_positionUpdateTimer {
this };
640 QTimer m_interimPositionUpdateTimer {
this };
641 QTimer m_visualPositionUpdateTimer {
this };
642 QTimer m_fsdSendMessageTimer {
this };
644 qint64 m_additionalOffsetTime = 0;
646 std::atomic_bool m_statistics {
false };
648 QVector<QPair<qint64, QString>> m_callByTime;
649 mutable QReadWriteLock m_lockStatistics { QReadWriteLock::Recursive };
654 QTextCodec *m_fsdTextCodec =
nullptr;
655 SimType m_simType = SimType::Unknown;
657 AtcRating m_atcRating = AtcRating::Unknown;
661 QString m_clientName;
662 QString m_hostApplication;
663 int m_versionMajor = 0;
664 int m_versionMinor = 0;
665 int m_protocolRevision = 0;
666 ServerType m_serverType = ServerType::LegacyFsd;
674 m_ownAircraftIcaoCode;
676 m_ownAirlineIcaoCode;
678 QString m_ownModelString;
679 std::atomic_bool m_sendLiveryString {
true };
680 std::atomic_bool m_sendModelString {
true };
682 mutable QReadWriteLock m_lockUserClientBuffered {
683 QReadWriteLock::Recursive
685 QString getOwnCallsignAsString()
const
687 QReadLocker l(&m_lockUserClientBuffered);
691 QQueue<QString> m_queuedFsdMessages;
694 void handleIllegalFsdState(
const QString &message);
696 static int constexpr c_maxOffsetTimes = 6;
697 static int constexpr c_processingIntervalMsec = 100;
698 static int constexpr c_updatePositionIntervalMsec =
700 static int constexpr c_updateInterimPositionIntervalMsec =
702 static int constexpr c_updateVisualPositionIntervalMsec =
704 static int constexpr c_sendFsdMsgIntervalMsec = 10;
705 bool m_stoppedSendingVisualPositions =
false;
706 bool m_serverWantsVisualPositions =
false;
707 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.
QString messageToFSDString(const T &message)
String which will be send.
#define SWIFT_CORE_EXPORT
Export a class or function from the library.