diff --git a/src/blackcore/fsd/fsdclient.cpp b/src/blackcore/fsd/fsdclient.cpp index 0b8918785..d41582cca 100644 --- a/src/blackcore/fsd/fsdclient.cpp +++ b/src/blackcore/fsd/fsdclient.cpp @@ -39,6 +39,7 @@ #include "blackcore/fsd/planeinforequestfsinn.h" #include "blackcore/fsd/planeinformationfsinn.h" #include "blackcore/fsd/revbclientparts.h" +#include "blackcore/fsd/rehost.h" #include "blackmisc/aviation/flightplan.h" #include "blackmisc/network/rawfsdmessage.h" @@ -1097,6 +1098,7 @@ namespace BlackCore::Fsd m_messageTypeMapping["#DL"] = MessageType::ServerHeartbeat; m_messageTypeMapping["#TM"] = MessageType::TextMessage; m_messageTypeMapping["#SB"] = MessageType::PilotClientCom; + m_messageTypeMapping["$XX"] = MessageType::Rehost; // Euroscope m_messageTypeMapping["SIMDATA"] = MessageType::EuroscopeSimData; @@ -1642,6 +1644,34 @@ namespace BlackCore::Fsd CLogMessage(this).debug(u"Set Config at %1 ") << offsetTimeMs ; } + void CFSDClient::handleRehost(const QStringList &tokens) + { + const Rehost rehost = Rehost::fromTokens(tokens); + + CLogMessage(this).info(u"Server requested we switch server to %1") << rehost.m_hostname; + + m_rehosting = true; + auto newSocket = new QTcpSocket(this); + connect(newSocket, &QTcpSocket::connected, this, [this, newSocket] + { + readDataFromSocket(); + CLogMessage(this).debug(u"Successfully switched server"); + QObject::disconnect(newSocket); + m_socket.reset(newSocket); + m_rehosting = false; + connectSocketSignals(); + readDataFromSocket(); + }); + connect(newSocket, &QTcpSocket::errorOccurred, this, [this, newSocket] + { + CLogMessage(this).warning(u"Failed to switch server: %1") << newSocket->errorString(); + m_rehosting = false; + delete newSocket; + if (m_socket->state() != QAbstractSocket::ConnectedState) { updateConnectionStatus(CConnectionStatus::Disconnected); } + }); + newSocket->connectToHost(rehost.m_hostname, m_socket->peerPort()); + } + void CFSDClient::handleCustomPilotPacket(const QStringList &tokens) { const QString subType = tokens.at(2); @@ -1757,11 +1787,15 @@ namespace BlackCore::Fsd void CFSDClient::printSocketError(QAbstractSocket::SocketError socketError) { + if (m_rehosting) { return; } + CLogMessage(this).error(u"FSD socket error: %1") << this->socketErrorString(socketError); } void CFSDClient::handleSocketError(QAbstractSocket::SocketError socketError) { + if (m_rehosting) { return; } + const QString error = this->socketErrorString(socketError); switch (socketError) { @@ -1893,6 +1927,7 @@ namespace BlackCore::Fsd void CFSDClient::clearState() { + m_rehosting = false; m_stoppedSendingVisualPositions = false; m_serverWantsVisualPositions = false; m_visualPositionUpdateSentCount = 0; @@ -2252,6 +2287,7 @@ namespace BlackCore::Fsd case MessageType::VisualPilotDataStopped: handleVisualPilotDataUpdate(tokens, messageType); break; case MessageType::VisualPilotDataToggle: handleVisualPilotDataToggle(tokens); break; case MessageType::EuroscopeSimData: handleEuroscopeSimData(tokens); break; + case MessageType::Rehost: handleRehost(tokens); break; // normally we should not get here default: diff --git a/src/blackcore/fsd/fsdclient.h b/src/blackcore/fsd/fsdclient.h index 3e2274bee..1e6a436e1 100644 --- a/src/blackcore/fsd/fsdclient.h +++ b/src/blackcore/fsd/fsdclient.h @@ -379,6 +379,7 @@ namespace BlackCore::Fsd 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); @@ -475,6 +476,7 @@ namespace BlackCore::Fsd std::unique_ptr m_socket = std::make_unique(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 }; diff --git a/src/blackcore/fsd/messagebase.h b/src/blackcore/fsd/messagebase.h index fad2c23e8..3d13799e8 100644 --- a/src/blackcore/fsd/messagebase.h +++ b/src/blackcore/fsd/messagebase.h @@ -52,6 +52,7 @@ enum class MessageType PilotClientCom, RevBClientParts, // IVAO only RevBPilotDescription, // -PD IVAO only not handled in swift + Rehost, }; namespace BlackCore::Fsd diff --git a/src/blackcore/fsd/rehost.cpp b/src/blackcore/fsd/rehost.cpp new file mode 100644 index 000000000..dd17cd756 --- /dev/null +++ b/src/blackcore/fsd/rehost.cpp @@ -0,0 +1,42 @@ +/* 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. + */ + +#include "rehost.h" +#include "serializer.h" + +#include "blackmisc/logmessage.h" + +using namespace BlackMisc; +using namespace BlackMisc::Aviation; + +namespace BlackCore::Fsd +{ + Rehost::Rehost() : MessageBase() + { } + + Rehost::Rehost(const QString &sender, const QString &hostname) + : MessageBase(sender, {}), + m_hostname(hostname) + { } + + QStringList Rehost::toTokens() const + { + return { m_sender, m_hostname }; + } + + Rehost Rehost::fromTokens(const QStringList &tokens) + { + if (tokens.size() < 2) + { + CLogMessage(static_cast(nullptr)).debug(u"Wrong number of arguments."); + return {}; + } + + return Rehost(tokens[0], tokens[1]); + } +} diff --git a/src/blackcore/fsd/rehost.h b/src/blackcore/fsd/rehost.h new file mode 100644 index 000000000..db4bf8181 --- /dev/null +++ b/src/blackcore/fsd/rehost.h @@ -0,0 +1,57 @@ +/* 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_REHOST_H +#define BLACKCORE_FSD_REHOST_H + +#include "messagebase.h" +#include "enums.h" + +namespace BlackCore::Fsd +{ + //! The server requests us to connect to a different server. + class BLACKCORE_EXPORT Rehost : public MessageBase + { + public: + //! Constructor + Rehost(const QString &sender, const QString &hostname); + + //! Message converted to tokens + QStringList toTokens() const; + + //! Construct from tokens + static Rehost fromTokens(const QStringList &tokens); + + //! PDU identifier + static QString pdu() { return "$XX"; } + + //! Properties + //! @{ + QString m_hostname; + //! @} + + private: + Rehost(); + }; + + //! Equal to operator + inline bool operator==(const Rehost &lhs, const Rehost &rhs) + { + return lhs.m_hostname == rhs.m_hostname; + } + + //! Not equal to operator + inline bool operator!=(const Rehost &lhs, const Rehost &rhs) + { + return !(lhs == rhs); + } +} + +#endif // guard