12
sunknown
c_cpp
3 years ago
8.7 kB
8
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...