12
sunknown
c_cpp
3 years ago
8.7 kB
5
Indexable
#include "DxClusterClient.h" #include <QTcpSocket> #include <TelnetSocket.h> #include <QDebug> #include <QNetworkInterface> struct DxClusterClient::impl { impl(DxClusterClient &contex) : m_context{contex} { m_socket.setSocket(&m_tcpSocket); m_timer.setSingleShot(true); pCurrent->onEnter(); QObject::connect(&m_tcpSocket, &QTcpSocket::stateChanged, &m_tcpSocket, [&](QAbstractSocket::SocketState socketStatus) { pCurrent->setConnectStatus(socketStatus); }); QObject::connect(&m_socket, &SDR::Telnet_2::message, &m_tcpSocket, [&](const QString &message) { pCurrent->setMessage(message); }); connect(&m_timer, &QTimer::timeout, &m_loop, &QEventLoop::quit); } ~impl() { } Status status() const { return m_status; } void setStatus(Status status) { m_status = status; } bool checkNetworkConnectivity() { bool connectivity = false; QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces(); for (int i = 0; i < interfaces.count(); i++) { QNetworkInterface interface = interfaces.at(i); if (interface.flags().testFlag(QNetworkInterface::IsUp) && !interface.flags().testFlag(QNetworkInterface::IsLoopBack) && interface.flags().testFlag(QNetworkInterface::IsRunning)) { connectivity = true; } } qDebug() << "Connectivity" << connectivity; return connectivity; } void connectToHost(const QString &callsign, const QString &host, quint16 port) { pCurrent->connectToHost(callsign, host, port); } void authorization(const QString &callsign){ qDebug() << "Authorization!!!"; setStatus(Status::Authorization); while (m_context.status() == Status::Authorization) { if (checkNetworkConnectivity()) { if (m_status != Status::Authorized) { m_socket.sendData(callsign); } setStatus(Status::Authorized); } else { close(); } } serverListening(); } void serverListening() { while (m_context.status() == Status::Authorized) { qDebug() << "listening"; m_timer.start(30000); m_loop.exec(); if (!checkNetworkConnectivity()) { qDebug() << "disconnecting"; setStatus(Status::Disconnecting); close(); } } } void close() { m_socket.close(); if (m_tcpSocket.waitForDisconnected(5000)) { qDebug() << "disconnected"; setStatus(Status::Disconnected); } } private: struct state_t { state_t(){} virtual ~state_t(){} virtual void onEnter(){} virtual void onExit(){} virtual void connectToHost(const QString &callsign, const QString &host, quint16 port){} virtual void close(){} virtual void setConnectStatus(QAbstractSocket::SocketState socketStatus){} virtual void setMessage(const QString &message){} }; struct idle_t : state_t { idle_t(impl &context) : m_context{context} {} void connectToHost(const QString &callsign, const QString &host, quint16 port) override { m_context.m_callsign = callsign; m_context.m_host = host; m_context.m_port = port; m_context.switchState(m_context.m_connecting); } private: impl &m_context; }; struct connecting_t : state_t { connecting_t(impl &context) : m_context{context} {} void onEnter() override { emit m_context.m_context.statusChanged(Status::Connecting); m_context.m_socket.connectToHost(m_context.m_host, m_context.m_port); m_context.m_timer.start(5000); m_context.m_loop.exec(); if (m_context.m_tcpSocket.state() == m_context.m_tcpSocket.ConnectedState) { //setStatus(Status::Connected); //authorization(callsign); qDebug() << "connected"; } } void setConnectStatus(QAbstractSocket::SocketState socketStatus) override{ if (socketStatus == QAbstractSocket::SocketState::ConnectedState) { m_context.switchState(m_context.m_authorizing); } else if ((QAbstractSocket::SocketState::UnconnectedState) || (QAbstractSocket::SocketState::ClosingState)) { m_context.switchState(m_context.m_reconnecting); } } void close() override{ m_context.switchState(m_context.m_idle); m_context.m_socket.close(); } void onExit() override { } private: impl &m_context; }; struct authorizing_t : state_t { authorizing_t(impl &context) : m_context{context}{ } void onEnter() override { } void setMessage(const QString &message) override{ if (isSetCallsign(message)) { } else if (isAuthorized(message)) { } else if (isError(message)) { } else { } } void setConnectStatus(QAbstractSocket::SocketState socketStatus) override{ if ((QAbstractSocket::SocketState::UnconnectedState) || (QAbstractSocket::SocketState::ClosingState)) { m_context.switchState(m_context.m_reconnecting); } } void close() override{ m_context.switchState(m_context.m_idle); m_context.m_socket.close(); } void onExit() override { } private: bool isSetCallsign(const QString &text) const { return false; } bool isAuthorized(const QString &text) const { return false; } bool isError(const QString &text) const { return false; } private: impl &m_context; }; struct process_t : state_t { process_t(impl &context) : m_context{context}{ } void onEnter() override { } void close() override{ m_context.switchState(m_context.m_idle); m_context.m_socket.close(); } void onExit() override { } private: impl &m_context; }; struct reconnect_t : state_t { reconnect_t(impl &context) : m_context{context}{ QObject::connect(&m_timer, &QTimer::timeout, &m_timer, [&](){ m_context.switchState(m_context.m_connecting); }); } void onEnter() override { m_timer.start(1000); } void onExit() override { m_timer.stop(); } void setConnectStatus(QAbstractSocket::SocketState socketStatus) { if ((QAbstractSocket::SocketState::UnconnectedState) || (QAbstractSocket::SocketState::ClosingState)) { m_context.switchState(m_context.m_reconnecting); } } void close() override{ m_context.switchState(m_context.m_idle); m_context.m_socket.close(); } private: impl &m_context; QTimer m_timer; }; void switchState(state_t &state) { if (pCurrent != &state) { pCurrent->onExit(); pCurrent = &state; pCurrent->onEnter(); } } private: DxClusterClient &m_context; QTcpSocket m_tcpSocket; SDR::Telnet_2 m_socket; Status m_status = Status::Disconnected; QTimer m_timer; QEventLoop m_loop; QString m_callsign {}; QString m_host {}; quint16 m_port {}; idle_t m_idle {*this}; connecting_t m_connecting {*this}; authorizing_t m_authorizing {*this}; process_t m_process {*this}; reconnect_t m_reconnecting {*this}; state_t *pCurrent {&m_idle}; }; DxClusterClient::DxClusterClient(QObject *parent) : QObject{parent}, pImpl{std::make_unique<impl>(*this)} { } DxClusterClient::~DxClusterClient() { } DxClusterClient::Status DxClusterClient::status() const { return pImpl->status(); } void DxClusterClient::connectToHost(const QString &callsign, const QString &host, quint16 port) { pImpl->connectToHost(callsign, host, port); } void DxClusterClient::authorization(const QString &callsign) { pImpl->authorization(callsign); } void DxClusterClient::serverListening() { pImpl->serverListening(); } void DxClusterClient::close() { pImpl->close(); }
Editor is loading...