383 lines
8.9 KiB
C++
383 lines
8.9 KiB
C++
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "PrtCnvSocketThread.hpp"
|
|
#include "PrtCnvDbThread.hpp"
|
|
#include "PrtCnvTelegramLogThread.hpp"
|
|
#include "PrtCnvThreadStarter.hpp"
|
|
#include "PrtCnvInjectionThread.hpp"
|
|
|
|
#include <QtNetwork/QTcpSocket>
|
|
#include <QtCore/QTimer>
|
|
|
|
namespace PrtCnv
|
|
{
|
|
|
|
|
|
|
|
|
|
PrtCnvSocketThread::PrtCnvSocketThread(PrtCnv::PrtCnvThreadStarter* a_parent, const char *loggerName)
|
|
: PrtCnvThread(a_parent, loggerName)
|
|
, m_ConnectionTimer(nullptr)
|
|
, m_Socket(nullptr)
|
|
, m_TickTimer(nullptr)
|
|
, m_ReceiveCounter(0)
|
|
, m_ReceiveAckCounter(0)
|
|
, m_State(PrtCnvSocketThread::e_INITIAL)
|
|
, m_DbThread(nullptr)
|
|
, m_ConnectTimeout(2000)
|
|
, m_DisconnectTimeout(10000)
|
|
, m_AliveTimeout(3000)
|
|
, m_TickTimeout(900)
|
|
, m_DoCleanup(false)
|
|
, m_LogThread(nullptr)
|
|
, m_InjectionThread(nullptr)
|
|
, m_currentHostAdressIndex(0)
|
|
{}
|
|
|
|
|
|
|
|
PrtCnvSocketThread::~PrtCnvSocketThread()
|
|
{
|
|
cleanup();
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t PrtCnvSocketThread::create(NGL::Settings *settings)
|
|
{
|
|
PrtCnvThread::create(settings);
|
|
|
|
createNewSocket();
|
|
|
|
m_ConnectionTimer = new QTimer(this);
|
|
connect(m_ConnectionTimer, &QTimer::timeout, this, &PrtCnvSocketThread::timeoutAliveAndConnection);
|
|
|
|
m_TickTimer = new QTimer(this);
|
|
connect(m_TickTimer, &QTimer::timeout, this, &PrtCnvSocketThread::timeoutTick);
|
|
|
|
m_DbThread = qobject_cast<PrtCnvDbThread*>(m_Parent->getOtherThread(PrtCnvApplication::e_Db));
|
|
m_LogThread = qobject_cast<PrtCnvTelegramLogThread*>(m_Parent->getOtherThread(PrtCnvApplication::e_Log));
|
|
m_InjectionThread = qobject_cast<PrtCnvInjectionThread*>(m_Parent->getOtherThread(PrtCnvApplication::e_Injection));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::createNewSocket()
|
|
{
|
|
INFO_LOG(m_logger) << "createNewSocket m_oldSocket=" << m_Socket;
|
|
Q_ASSERT(QThread::currentThreadId() == m_currentThreadId);
|
|
|
|
if (m_Socket)
|
|
{
|
|
m_Socket->disconnectFromHost();
|
|
m_Socket->disconnect();
|
|
if (m_Socket->state() != QAbstractSocket::UnconnectedState)
|
|
m_Socket->waitForDisconnected();
|
|
m_Socket->deleteLater();
|
|
}
|
|
|
|
m_Socket = new QTcpSocket(this);
|
|
qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
|
|
qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
|
|
|
|
connect(m_Socket, &QTcpSocket::connected, this, &PrtCnvSocketThread::connected, Qt::QueuedConnection);
|
|
connect(m_Socket, &QTcpSocket::disconnected, this, &PrtCnvSocketThread::disconnected, Qt::QueuedConnection);
|
|
connect(m_Socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &PrtCnvSocketThread::error, Qt::QueuedConnection);
|
|
connect(m_Socket, &QTcpSocket::hostFound, this, &PrtCnvSocketThread::hostFound, Qt::QueuedConnection);
|
|
connect(m_Socket, &QTcpSocket::stateChanged, this, &PrtCnvSocketThread::stateChanged);
|
|
connect(m_Socket, &QTcpSocket::readyRead, this, &PrtCnvSocketThread::readyRead, Qt::QueuedConnection);
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t PrtCnvSocketThread::destroy()
|
|
{
|
|
PrtCnvThread::destroy();
|
|
cleanup();
|
|
return 0;
|
|
}
|
|
|
|
void PrtCnvSocketThread::cleanup()
|
|
{
|
|
delete m_Socket; m_Socket = nullptr;
|
|
delete m_ConnectionTimer; m_ConnectionTimer = nullptr;
|
|
delete m_TickTimer; m_TickTimer = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t PrtCnvSocketThread::init()
|
|
{
|
|
INFO_LOG(m_logger) << "PrtCnvSocketThread::init()";
|
|
PrtCnvThread::init();
|
|
m_State = e_INITIAL;
|
|
|
|
m_ConnectTimeout = m_Config->getInteger(getName(), QStringLiteral("ConnectTimeout"), 2000);
|
|
m_DisconnectTimeout = m_Config->getInteger(getName(), QStringLiteral("DisconnectTimeout"), 10000);
|
|
m_AliveTimeout = m_Config->getInteger(getName(), QStringLiteral("AliveTimeout"), 3000);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::connectSocket()
|
|
{
|
|
int sockState = m_Socket ? m_Socket->state() : -1;
|
|
INFO_LOG(m_logger) << "connectSocket m_Socket=" << m_Socket << " state=" << m_State << " socketState=" << sockState;
|
|
if (e_WORKING != m_State && e_REGISTERING != m_State)
|
|
{
|
|
if (m_Socket)
|
|
{
|
|
m_Socket->disconnectFromHost();
|
|
if (m_Socket->state() != QAbstractSocket::UnconnectedState)
|
|
m_Socket->waitForDisconnected();
|
|
}
|
|
|
|
createNewSocket();
|
|
|
|
if(m_hostAdresses.isEmpty())
|
|
readHostAdresses();
|
|
const QString hostname = m_hostAdresses.at(m_currentHostAdressIndex).first;
|
|
const uint16_t port = m_hostAdresses.at(m_currentHostAdressIndex).second;
|
|
m_currentHostAdressIndex = ((m_currentHostAdressIndex + 1) % m_hostAdresses.size());
|
|
INFO_LOG(m_logger) << "Connecting to " << hostname << ":" << port << " m_Socket=" << m_Socket;
|
|
m_Socket->connectToHost(hostname, port);
|
|
m_State = e_CONNECTING;
|
|
startConnectionTimer();
|
|
}
|
|
else
|
|
{
|
|
WARNING_LOG(m_logger) << getName() << ": connectSocket called, but m_State is " << m_State;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::disconnectSocket()
|
|
{
|
|
m_Socket->disconnectFromHost();
|
|
startDisconnectionTimer();
|
|
m_State = e_DISCONNECTING;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::connected()
|
|
{
|
|
INFO_LOG(m_logger) << "connected (implement connected() in inherited class, if you want use this signal...)";
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::disconnected()
|
|
{
|
|
INFO_LOG(m_logger) << "got signal 'disconnected' (implement disconnected() in inherited class, if you want use this signal...)";
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::readyRead()
|
|
{
|
|
INFO_LOG(m_logger) << "got signal 'newData' (implement newData() in inherited class, if you want use this signal...)";
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::timeoutAliveAndConnection()
|
|
{
|
|
INFO_LOG(m_logger) << "got signal 'reconnectTimeout' (implement reconnectTimeout() in inherited class, if you want use this signal...)";
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::error(QAbstractSocket::SocketError a_socketError)
|
|
{
|
|
switch (a_socketError)
|
|
{
|
|
case QAbstractSocket::ConnectionRefusedError:
|
|
ERROR_LOG(m_logger) << getName() << ": ConnectionRefusedError m_State=" << m_State;
|
|
break;
|
|
case QAbstractSocket::RemoteHostClosedError:
|
|
ERROR_LOG(m_logger) << getName() << ": RemoteHostClosedError";
|
|
break;
|
|
case QAbstractSocket::HostNotFoundError:
|
|
|
|
break;
|
|
default:
|
|
ERROR_LOG(m_logger) << getName() << ": got signal 'error(QAbstractSocket::SocketError=" << a_socketError << ")'";
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::hostFound()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::stateChanged(QAbstractSocket::SocketState a_socketState)
|
|
{
|
|
Q_UNUSED(a_socketState);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::storeRadioTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_telegram,
|
|
const uint32_t a_readCounter)
|
|
{
|
|
m_DbThread->storeRadioTelegram(a_telegram, a_readCounter);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::startAliveTimer()
|
|
{
|
|
m_ConnectionTimer->setInterval(m_AliveTimeout);
|
|
m_ConnectionTimer->start();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::startConnectionTimer()
|
|
{
|
|
m_ConnectionTimer->setInterval(m_ConnectTimeout);
|
|
m_ConnectionTimer->start();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::startDisconnectionTimer()
|
|
{
|
|
m_ConnectionTimer->setInterval(m_DisconnectTimeout);
|
|
m_ConnectionTimer->start();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrtCnvSocketThread::startTickTimer()
|
|
{
|
|
|
|
m_TickTimer->setInterval(m_TickTimeout);
|
|
m_TickTimer->start();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool PrtCnvSocketThread::checkAndUpdateReceiveCounter(const uint32_t a_counter, const uint32_t a_maxCounter, const uint32_t a_startCounter)
|
|
{
|
|
TRACE_LOG(m_logger) << "checkAndUpdateReceiveCounter: " << a_counter << ", " << m_ReceiveCounter;
|
|
|
|
if (a_maxCounter == ++m_ReceiveCounter)
|
|
{
|
|
m_ReceiveCounter = a_startCounter;
|
|
}
|
|
|
|
if (m_ReceiveCounter != a_counter)
|
|
{
|
|
|
|
{
|
|
if (m_ReceiveCounter > a_counter)
|
|
{
|
|
ERROR_LOG(m_logger) << "It seems, the telegram with counter " << a_counter << " was resent from "
|
|
<< getName() << "! Expected: " << m_ReceiveCounter;
|
|
}
|
|
else
|
|
{
|
|
ERROR_LOG(m_logger) << "It seems, we lost one or several telegrams from " << getName()
|
|
<< ": receive-counter of received telegram: " << a_counter << "; Expected: " << m_ReceiveCounter;
|
|
}
|
|
}
|
|
#if 0
|
|
m_ReceiveCounter--;
|
|
return false;
|
|
#else
|
|
m_ReceiveCounter = a_counter;
|
|
return true;
|
|
#endif
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void PrtCnvSocketThread::readHostAdresses()
|
|
{
|
|
QString host = m_Config->getString(getName(), QStringLiteral("HostName"), QStringLiteral("127.0.0.1"));
|
|
uint16_t port = m_Config->getInteger(getName(), QStringLiteral("Port"), 4934);
|
|
m_hostAdresses.push_back(qMakePair(host, port));
|
|
for (int i = 1; i < 10; ++i) {
|
|
const QString hostName = QLatin1String("HostName") + QString::number(i);
|
|
const QString portName = QLatin1String("Port") + QString::number(i);
|
|
host = m_Config->getString(getName(), hostName, QString());
|
|
port = m_Config->getInteger(getName(), portName, 0);
|
|
if (host.isEmpty() || port == 0)
|
|
continue;
|
|
m_hostAdresses.push_back(qMakePair(host, port));
|
|
}
|
|
for (const auto &p : std::as_const(m_hostAdresses)) {
|
|
INFO_LOG(m_logger) << "Read Host Adress " << p.first
|
|
<< ":" << p.second
|
|
<< " from settings";
|
|
}
|
|
}
|
|
|
|
|
|
}
|