Merge PR #530: Add ping retry feature and provide it to the monitor
This commit is contained in:
commit
68be029ede
@ -93,7 +93,7 @@ NetworkDeviceDiscoveryImpl::NetworkDeviceDiscoveryImpl(QObject *parent) :
|
|||||||
|
|
||||||
NetworkDeviceDiscoveryImpl::~NetworkDeviceDiscoveryImpl()
|
NetworkDeviceDiscoveryImpl::~NetworkDeviceDiscoveryImpl()
|
||||||
{
|
{
|
||||||
|
delete m_cacheSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkDeviceDiscoveryReply *NetworkDeviceDiscoveryImpl::discover()
|
NetworkDeviceDiscoveryReply *NetworkDeviceDiscoveryImpl::discover()
|
||||||
@ -146,16 +146,21 @@ bool NetworkDeviceDiscoveryImpl::running() const
|
|||||||
|
|
||||||
NetworkDeviceMonitor *NetworkDeviceDiscoveryImpl::registerMonitor(const MacAddress &macAddress)
|
NetworkDeviceMonitor *NetworkDeviceDiscoveryImpl::registerMonitor(const MacAddress &macAddress)
|
||||||
{
|
{
|
||||||
qCInfo(dcNetworkDeviceDiscovery()) << "Register new network device monitor for" << macAddress;
|
|
||||||
// Make sure we create only one monitor per MAC
|
|
||||||
if (m_monitors.contains(macAddress))
|
|
||||||
return m_monitors.value(macAddress);
|
|
||||||
|
|
||||||
if (macAddress.isNull()) {
|
if (macAddress.isNull()) {
|
||||||
qCWarning(dcNetworkDeviceDiscovery()) << "Could not register monitor for invalid" << macAddress;
|
qCWarning(dcNetworkDeviceDiscovery()) << "Could not register monitor for invalid" << macAddress;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we create only one monitor per MAC and keep track how many user
|
||||||
|
// have access to this monitor otherwise an unregister could cause a crash in
|
||||||
|
// an other plugin plugin which might still need it
|
||||||
|
if (m_monitors.contains(macAddress)) {
|
||||||
|
m_monitorsReferenceCount[macAddress] += 1;
|
||||||
|
qCInfo(dcNetworkDeviceDiscovery()) << "Register network device monitor for" << macAddress << "which already exists. Returning existing monitor having now" << m_monitorsReferenceCount[macAddress] << "references.";
|
||||||
|
return m_monitors.value(macAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
qCInfo(dcNetworkDeviceDiscovery()) << "Register new network device monitor for" << macAddress;
|
||||||
|
|
||||||
// Fill in cached information
|
// Fill in cached information
|
||||||
NetworkDeviceInfo info;
|
NetworkDeviceInfo info;
|
||||||
@ -168,6 +173,7 @@ NetworkDeviceMonitor *NetworkDeviceDiscoveryImpl::registerMonitor(const MacAddre
|
|||||||
NetworkDeviceMonitorImpl *monitor = new NetworkDeviceMonitorImpl(macAddress, this);
|
NetworkDeviceMonitorImpl *monitor = new NetworkDeviceMonitorImpl(macAddress, this);
|
||||||
monitor->setNetworkDeviceInfo(info);
|
monitor->setNetworkDeviceInfo(info);
|
||||||
m_monitors.insert(macAddress, monitor);
|
m_monitors.insert(macAddress, monitor);
|
||||||
|
m_monitorsReferenceCount[macAddress] = 1;
|
||||||
|
|
||||||
if (!available()) {
|
if (!available()) {
|
||||||
qCWarning(dcNetworkDeviceDiscovery()) << "Registered monitor but the hardware resource is not available. The monitor will not work as expected" << monitor;
|
qCWarning(dcNetworkDeviceDiscovery()) << "Registered monitor but the hardware resource is not available. The monitor will not work as expected" << monitor;
|
||||||
@ -189,10 +195,19 @@ NetworkDeviceMonitor *NetworkDeviceDiscoveryImpl::registerMonitor(const MacAddre
|
|||||||
|
|
||||||
void NetworkDeviceDiscoveryImpl::unregisterMonitor(const MacAddress &macAddress)
|
void NetworkDeviceDiscoveryImpl::unregisterMonitor(const MacAddress &macAddress)
|
||||||
{
|
{
|
||||||
|
if (m_monitorsReferenceCount.contains(macAddress)) {
|
||||||
|
m_monitorsReferenceCount[macAddress] -= 1;
|
||||||
|
if (m_monitorsReferenceCount[macAddress] > 0) {
|
||||||
|
qCDebug(dcNetworkDeviceDiscovery()) << "Unregistered monitor for" << macAddress.toString() << "but keeping the monitor. There are still" << m_monitorsReferenceCount[macAddress] << "references to it.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_monitors.contains(macAddress)) {
|
if (m_monitors.contains(macAddress)) {
|
||||||
NetworkDeviceMonitor *monitor = m_monitors.take(macAddress);
|
NetworkDeviceMonitor *monitor = m_monitors.take(macAddress);
|
||||||
qCInfo(dcNetworkDeviceDiscovery()) << "Unregister" << monitor;
|
qCInfo(dcNetworkDeviceDiscovery()) << "Unregister" << monitor;
|
||||||
monitor->deleteLater();
|
monitor->deleteLater();
|
||||||
|
m_monitorsReferenceCount.remove(macAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,34 +216,19 @@ void NetworkDeviceDiscoveryImpl::unregisterMonitor(NetworkDeviceMonitor *network
|
|||||||
unregisterMonitor(MacAddress(networkDeviceMonitor->networkDeviceInfo().macAddress()));
|
unregisterMonitor(MacAddress(networkDeviceMonitor->networkDeviceInfo().macAddress()));
|
||||||
}
|
}
|
||||||
|
|
||||||
PingReply *NetworkDeviceDiscoveryImpl::ping(const QHostAddress &address)
|
PingReply *NetworkDeviceDiscoveryImpl::ping(const QHostAddress &address, uint retries)
|
||||||
{
|
{
|
||||||
|
PingReply *reply = m_ping->ping(address, retries);
|
||||||
// Note: we use any ping used trough this method also for the monitor evaluation
|
// Note: we use any ping used trough this method also for the monitor evaluation
|
||||||
PingReply *reply = m_ping->ping(address);
|
watchPingReply(reply);
|
||||||
connect(reply, &PingReply::finished, this, [=](){
|
return reply;
|
||||||
|
}
|
||||||
// Search cache for mac address and update last seen
|
|
||||||
if (reply->error() == PingReply::ErrorNoError) {
|
|
||||||
foreach (const NetworkDeviceInfo &info, m_networkInfoCache) {
|
|
||||||
if (info.address() == address) {
|
|
||||||
// Found info for this ip, update the cache
|
|
||||||
MacAddress macAddress(info.macAddress());
|
|
||||||
if (!macAddress.isNull() && m_networkInfoCache.contains(macAddress)) {
|
|
||||||
m_lastSeen[macAddress] = QDateTime::currentDateTime();
|
|
||||||
saveNetworkDeviceCache(m_networkInfoCache.value(macAddress));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update any monitor
|
|
||||||
foreach (NetworkDeviceMonitorImpl *monitor, m_monitors.values()) {
|
|
||||||
if (monitor->networkDeviceInfo().address() == address) {
|
|
||||||
processMonitorPingResult(reply, monitor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
PingReply *NetworkDeviceDiscoveryImpl::ping(const QHostAddress &address, bool lookupHost, uint retries)
|
||||||
|
{
|
||||||
|
PingReply *reply = m_ping->ping(address, lookupHost, retries);
|
||||||
|
// Note: we use any ping used trough this method also for the monitor evaluation
|
||||||
|
watchPingReply(reply);
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +304,8 @@ void NetworkDeviceDiscoveryImpl::pingAllNetworkDevices()
|
|||||||
if (targetAddress == entry.ip())
|
if (targetAddress == entry.ip())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PingReply *reply = ping(targetAddress);
|
// Retry only once to ping a device and lookup the hostname on success
|
||||||
|
PingReply *reply = ping(targetAddress, true, 1);
|
||||||
m_runningPingRepies.append(reply);
|
m_runningPingRepies.append(reply);
|
||||||
connect(reply, &PingReply::finished, this, [=](){
|
connect(reply, &PingReply::finished, this, [=](){
|
||||||
m_runningPingRepies.removeAll(reply);
|
m_runningPingRepies.removeAll(reply);
|
||||||
@ -333,11 +334,37 @@ void NetworkDeviceDiscoveryImpl::processMonitorPingResult(PingReply *reply, Netw
|
|||||||
monitor->setLastSeen(QDateTime::currentDateTime());
|
monitor->setLastSeen(QDateTime::currentDateTime());
|
||||||
monitor->setReachable(true);
|
monitor->setReachable(true);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << "Failed to ping device from" << monitor << reply->error();
|
qCDebug(dcNetworkDeviceDiscovery()) << "Failed to ping device from" << monitor << "retrying" << reply->retries() << "times:" << reply->error();
|
||||||
monitor->setReachable(false);
|
monitor->setReachable(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetworkDeviceDiscoveryImpl::watchPingReply(PingReply *reply)
|
||||||
|
{
|
||||||
|
connect(reply, &PingReply::finished, this, [=](){
|
||||||
|
// Search cache for mac address and update last seen
|
||||||
|
if (reply->error() == PingReply::ErrorNoError) {
|
||||||
|
foreach (const NetworkDeviceInfo &info, m_networkInfoCache) {
|
||||||
|
if (info.address() == reply->targetHostAddress()) {
|
||||||
|
// Found info for this ip, update the cache
|
||||||
|
MacAddress macAddress(info.macAddress());
|
||||||
|
if (!macAddress.isNull() && m_networkInfoCache.contains(macAddress)) {
|
||||||
|
m_lastSeen[macAddress] = QDateTime::currentDateTime();
|
||||||
|
saveNetworkDeviceCache(m_networkInfoCache.value(macAddress));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update any monitor
|
||||||
|
foreach (NetworkDeviceMonitorImpl *monitor, m_monitors.values()) {
|
||||||
|
if (monitor->networkDeviceInfo().address() == reply->targetHostAddress()) {
|
||||||
|
processMonitorPingResult(reply, monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void NetworkDeviceDiscoveryImpl::loadNetworkDeviceCache()
|
void NetworkDeviceDiscoveryImpl::loadNetworkDeviceCache()
|
||||||
{
|
{
|
||||||
qCInfo(dcNetworkDeviceDiscovery()) << "Loading cached network device information from" << m_cacheSettings->fileName();
|
qCInfo(dcNetworkDeviceDiscovery()) << "Loading cached network device information from" << m_cacheSettings->fileName();
|
||||||
@ -356,6 +383,7 @@ void NetworkDeviceDiscoveryImpl::loadNetworkDeviceCache()
|
|||||||
if (lastSeen.date().addDays(m_cacheCleanupPeriod) < now.date()) {
|
if (lastSeen.date().addDays(m_cacheCleanupPeriod) < now.date()) {
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << "Removing network device cache entry since it did not show up within the last" << m_cacheCleanupPeriod << "days" << mac.toString();
|
qCDebug(dcNetworkDeviceDiscovery()) << "Removing network device cache entry since it did not show up within the last" << m_cacheCleanupPeriod << "days" << mac.toString();
|
||||||
m_cacheSettings->remove("");
|
m_cacheSettings->remove("");
|
||||||
|
m_cacheSettings->endGroup(); // mac address
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,16 +419,19 @@ void NetworkDeviceDiscoveryImpl::removeFromNetworkDeviceCache(const MacAddress &
|
|||||||
|
|
||||||
m_networkInfoCache.remove(macAddress);
|
m_networkInfoCache.remove(macAddress);
|
||||||
m_lastSeen.remove(macAddress);
|
m_lastSeen.remove(macAddress);
|
||||||
|
|
||||||
m_cacheSettings->beginGroup("NetworkDeviceInfos");
|
m_cacheSettings->beginGroup("NetworkDeviceInfos");
|
||||||
m_cacheSettings->beginGroup(macAddress.toString());
|
m_cacheSettings->beginGroup(macAddress.toString());
|
||||||
m_cacheSettings->remove("");
|
m_cacheSettings->remove("");
|
||||||
m_cacheSettings->endGroup(); // mac address
|
m_cacheSettings->endGroup(); // mac address
|
||||||
m_cacheSettings->endGroup(); // NetworkDeviceInfos
|
m_cacheSettings->endGroup(); // NetworkDeviceInfos
|
||||||
|
m_cacheSettings->sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkDeviceDiscoveryImpl::saveNetworkDeviceCache(const NetworkDeviceInfo &deviceInfo)
|
void NetworkDeviceDiscoveryImpl::saveNetworkDeviceCache(const NetworkDeviceInfo &deviceInfo)
|
||||||
{
|
{
|
||||||
|
if (!deviceInfo.isValid() || !deviceInfo.isComplete())
|
||||||
|
return;
|
||||||
|
|
||||||
m_cacheSettings->beginGroup("NetworkDeviceInfos");
|
m_cacheSettings->beginGroup("NetworkDeviceInfos");
|
||||||
m_cacheSettings->beginGroup(deviceInfo.macAddress());
|
m_cacheSettings->beginGroup(deviceInfo.macAddress());
|
||||||
m_cacheSettings->setValue("address", deviceInfo.address().toString());
|
m_cacheSettings->setValue("address", deviceInfo.address().toString());
|
||||||
@ -410,6 +441,7 @@ void NetworkDeviceDiscoveryImpl::saveNetworkDeviceCache(const NetworkDeviceInfo
|
|||||||
m_cacheSettings->setValue("lastSeen", convertMinuteBased(m_lastSeen.value(MacAddress(deviceInfo.macAddress()))).toMSecsSinceEpoch());
|
m_cacheSettings->setValue("lastSeen", convertMinuteBased(m_lastSeen.value(MacAddress(deviceInfo.macAddress()))).toMSecsSinceEpoch());
|
||||||
m_cacheSettings->endGroup(); // mac address
|
m_cacheSettings->endGroup(); // mac address
|
||||||
m_cacheSettings->endGroup(); // NetworkDeviceInfos
|
m_cacheSettings->endGroup(); // NetworkDeviceInfos
|
||||||
|
m_cacheSettings->sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkDeviceDiscoveryImpl::updateCache(const NetworkDeviceInfo &deviceInfo)
|
void NetworkDeviceDiscoveryImpl::updateCache(const NetworkDeviceInfo &deviceInfo)
|
||||||
@ -432,6 +464,12 @@ void NetworkDeviceDiscoveryImpl::updateCache(const NetworkDeviceInfo &deviceInfo
|
|||||||
|
|
||||||
void NetworkDeviceDiscoveryImpl::evaluateMonitor(NetworkDeviceMonitorImpl *monitor)
|
void NetworkDeviceDiscoveryImpl::evaluateMonitor(NetworkDeviceMonitorImpl *monitor)
|
||||||
{
|
{
|
||||||
|
if (monitor->networkDeviceInfo().address().isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (monitor->currentPingReply())
|
||||||
|
return;
|
||||||
|
|
||||||
// Start action if we have not seen the device for gracePeriod seconds
|
// Start action if we have not seen the device for gracePeriod seconds
|
||||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||||
|
|
||||||
@ -449,15 +487,20 @@ void NetworkDeviceDiscoveryImpl::evaluateMonitor(NetworkDeviceMonitorImpl *monit
|
|||||||
if (!requiresRefresh)
|
if (!requiresRefresh)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (monitor->networkDeviceInfo().address().isNull())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Try to ping first
|
// Try to ping first
|
||||||
qCDebug(dcNetworkDeviceDiscovery()) << monitor << "try to ping" << monitor->networkDeviceInfo().address().toString();
|
qCDebug(dcNetworkDeviceDiscovery()) << monitor << "try to ping" << monitor->networkDeviceInfo().address().toString();
|
||||||
|
PingReply *reply = m_ping->ping(monitor->networkDeviceInfo().address(), monitor->pingRetries());
|
||||||
|
monitor->setCurrentPingReply(reply);
|
||||||
monitor->setLastConnectionAttempt(currentDateTime);
|
monitor->setLastConnectionAttempt(currentDateTime);
|
||||||
|
|
||||||
PingReply *reply = m_ping->ping(monitor->networkDeviceInfo().address());
|
connect(reply, &PingReply::retry, monitor, [=](PingReply::Error error, uint retryCount){
|
||||||
|
Q_UNUSED(error)
|
||||||
|
Q_UNUSED(retryCount)
|
||||||
|
monitor->setLastConnectionAttempt(QDateTime::currentDateTime());
|
||||||
|
});
|
||||||
|
|
||||||
connect(reply, &PingReply::finished, monitor, [=](){
|
connect(reply, &PingReply::finished, monitor, [=](){
|
||||||
|
monitor->setCurrentPingReply(nullptr);
|
||||||
processMonitorPingResult(reply, monitor);
|
processMonitorPingResult(reply, monitor);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,7 +71,8 @@ public:
|
|||||||
void unregisterMonitor(const MacAddress &macAddress) override;
|
void unregisterMonitor(const MacAddress &macAddress) override;
|
||||||
void unregisterMonitor(NetworkDeviceMonitor *networkDeviceMonitor) override;
|
void unregisterMonitor(NetworkDeviceMonitor *networkDeviceMonitor) override;
|
||||||
|
|
||||||
PingReply *ping(const QHostAddress &address) override;
|
PingReply *ping(const QHostAddress &address, uint retries = 3) override;
|
||||||
|
PingReply *ping(const QHostAddress &address, bool lookupHost, uint retries = 3);
|
||||||
|
|
||||||
MacAddressDatabaseReply *lookupMacAddress(const QString &macAddress) override;
|
MacAddressDatabaseReply *lookupMacAddress(const QString &macAddress) override;
|
||||||
MacAddressDatabaseReply *lookupMacAddress(const MacAddress &macAddress) override;
|
MacAddressDatabaseReply *lookupMacAddress(const MacAddress &macAddress) override;
|
||||||
@ -104,6 +105,7 @@ private:
|
|||||||
QList<PingReply *> m_runningPingRepies;
|
QList<PingReply *> m_runningPingRepies;
|
||||||
|
|
||||||
QHash<MacAddress, NetworkDeviceMonitorImpl *> m_monitors;
|
QHash<MacAddress, NetworkDeviceMonitorImpl *> m_monitors;
|
||||||
|
QHash<MacAddress, int> m_monitorsReferenceCount;
|
||||||
QHash<MacAddress, QDateTime> m_lastSeen;
|
QHash<MacAddress, QDateTime> m_lastSeen;
|
||||||
|
|
||||||
QSettings *m_cacheSettings;
|
QSettings *m_cacheSettings;
|
||||||
@ -113,6 +115,8 @@ private:
|
|||||||
|
|
||||||
void processMonitorPingResult(PingReply *reply, NetworkDeviceMonitorImpl *monitor);
|
void processMonitorPingResult(PingReply *reply, NetworkDeviceMonitorImpl *monitor);
|
||||||
|
|
||||||
|
void watchPingReply(PingReply *reply);
|
||||||
|
|
||||||
void loadNetworkDeviceCache();
|
void loadNetworkDeviceCache();
|
||||||
void removeFromNetworkDeviceCache(const MacAddress &macAddress);
|
void removeFromNetworkDeviceCache(const MacAddress &macAddress);
|
||||||
void saveNetworkDeviceCache(const NetworkDeviceInfo &deviceInfo);
|
void saveNetworkDeviceCache(const NetworkDeviceInfo &deviceInfo);
|
||||||
|
|||||||
@ -29,6 +29,9 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "networkdevicemonitorimpl.h"
|
#include "networkdevicemonitorimpl.h"
|
||||||
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcNetworkDeviceDiscovery)
|
||||||
|
|
||||||
namespace nymeaserver {
|
namespace nymeaserver {
|
||||||
|
|
||||||
@ -41,7 +44,9 @@ NetworkDeviceMonitorImpl::NetworkDeviceMonitorImpl(const MacAddress &macAddress,
|
|||||||
|
|
||||||
NetworkDeviceMonitorImpl::~NetworkDeviceMonitorImpl()
|
NetworkDeviceMonitorImpl::~NetworkDeviceMonitorImpl()
|
||||||
{
|
{
|
||||||
|
if (m_currentPingReply) {
|
||||||
|
m_currentPingReply->abort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MacAddress NetworkDeviceMonitorImpl::macAddress() const
|
MacAddress NetworkDeviceMonitorImpl::macAddress() const
|
||||||
@ -73,6 +78,7 @@ void NetworkDeviceMonitorImpl::setReachable(bool reachable)
|
|||||||
if (m_reachable == reachable)
|
if (m_reachable == reachable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
qCDebug(dcNetworkDeviceDiscovery()) << this << (reachable ? "is now reachable" : "is not reachable any more.");
|
||||||
m_reachable = reachable;
|
m_reachable = reachable;
|
||||||
emit reachableChanged(m_reachable);
|
emit reachableChanged(m_reachable);
|
||||||
}
|
}
|
||||||
@ -92,6 +98,26 @@ void NetworkDeviceMonitorImpl::setLastSeen(const QDateTime &lastSeen)
|
|||||||
emit lastSeenChanged(m_lastSeen);
|
emit lastSeenChanged(m_lastSeen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint NetworkDeviceMonitorImpl::pingRetries() const
|
||||||
|
{
|
||||||
|
return m_pingRetries;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkDeviceMonitorImpl::setPingRetries(uint pingRetries)
|
||||||
|
{
|
||||||
|
m_pingRetries = pingRetries;
|
||||||
|
}
|
||||||
|
|
||||||
|
PingReply *NetworkDeviceMonitorImpl::currentPingReply() const
|
||||||
|
{
|
||||||
|
return m_currentPingReply;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkDeviceMonitorImpl::setCurrentPingReply(PingReply *reply)
|
||||||
|
{
|
||||||
|
m_currentPingReply = reply;
|
||||||
|
}
|
||||||
|
|
||||||
QDateTime NetworkDeviceMonitorImpl::lastConnectionAttempt() const
|
QDateTime NetworkDeviceMonitorImpl::lastConnectionAttempt() const
|
||||||
{
|
{
|
||||||
return m_lastConnectionAttempt;
|
return m_lastConnectionAttempt;
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
#include "network/networkdevicemonitor.h"
|
#include "network/networkdevicemonitor.h"
|
||||||
|
#include "network/pingreply.h"
|
||||||
|
|
||||||
namespace nymeaserver {
|
namespace nymeaserver {
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ class NetworkDeviceMonitorImpl : public NetworkDeviceMonitor
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit NetworkDeviceMonitorImpl(const MacAddress &macAddress, QObject *parent = nullptr);
|
explicit NetworkDeviceMonitorImpl(const MacAddress &macAddress, QObject *parent = nullptr);
|
||||||
~NetworkDeviceMonitorImpl();
|
~NetworkDeviceMonitorImpl() override;
|
||||||
|
|
||||||
MacAddress macAddress() const override;
|
MacAddress macAddress() const override;
|
||||||
|
|
||||||
@ -57,16 +58,24 @@ public:
|
|||||||
QDateTime lastSeen() const override;
|
QDateTime lastSeen() const override;
|
||||||
void setLastSeen(const QDateTime &lastSeen);
|
void setLastSeen(const QDateTime &lastSeen);
|
||||||
|
|
||||||
|
uint pingRetries() const override;
|
||||||
|
void setPingRetries(uint pingRetries) override;
|
||||||
|
|
||||||
|
PingReply *currentPingReply() const;
|
||||||
|
void setCurrentPingReply(PingReply *reply);
|
||||||
|
|
||||||
QDateTime lastConnectionAttempt() const;
|
QDateTime lastConnectionAttempt() const;
|
||||||
void setLastConnectionAttempt(const QDateTime &lastConnectionAttempt);
|
void setLastConnectionAttempt(const QDateTime &lastConnectionAttempt);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetworkDeviceInfo m_networkDeviceInfo;
|
NetworkDeviceInfo m_networkDeviceInfo;
|
||||||
MacAddress m_macAddress;
|
MacAddress m_macAddress;
|
||||||
bool m_reachable = false;
|
bool m_reachable = false;
|
||||||
QDateTime m_lastSeen;
|
QDateTime m_lastSeen;
|
||||||
QDateTime m_lastConnectionAttempt;
|
QDateTime m_lastConnectionAttempt;
|
||||||
|
uint m_pingRetries = 5;
|
||||||
|
PingReply *m_currentPingReply = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,7 +60,7 @@ public:
|
|||||||
virtual void unregisterMonitor(const MacAddress &macAddress) = 0;
|
virtual void unregisterMonitor(const MacAddress &macAddress) = 0;
|
||||||
virtual void unregisterMonitor(NetworkDeviceMonitor *networkDeviceMonitor) = 0;
|
virtual void unregisterMonitor(NetworkDeviceMonitor *networkDeviceMonitor) = 0;
|
||||||
|
|
||||||
virtual PingReply *ping(const QHostAddress &address) = 0;
|
virtual PingReply *ping(const QHostAddress &address, uint retries = 3) = 0;
|
||||||
|
|
||||||
virtual MacAddressDatabaseReply *lookupMacAddress(const QString &macAddress) = 0;
|
virtual MacAddressDatabaseReply *lookupMacAddress(const QString &macAddress) = 0;
|
||||||
virtual MacAddressDatabaseReply *lookupMacAddress(const MacAddress &macAddress) = 0;
|
virtual MacAddressDatabaseReply *lookupMacAddress(const MacAddress &macAddress) = 0;
|
||||||
|
|||||||
@ -53,6 +53,9 @@ public:
|
|||||||
virtual bool reachable() const = 0;
|
virtual bool reachable() const = 0;
|
||||||
virtual QDateTime lastSeen() const = 0;
|
virtual QDateTime lastSeen() const = 0;
|
||||||
|
|
||||||
|
virtual uint pingRetries() const = 0;
|
||||||
|
virtual void setPingRetries(uint pingRetries) = 0;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void reachableChanged(bool reachable);
|
void reachableChanged(bool reachable);
|
||||||
void lastSeenChanged(const QDateTime &lastSeen);
|
void lastSeenChanged(const QDateTime &lastSeen);
|
||||||
|
|||||||
@ -111,11 +111,23 @@ PingReply::Error Ping::error() const
|
|||||||
return m_error;
|
return m_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
PingReply *Ping::ping(const QHostAddress &hostAddress)
|
PingReply *Ping::ping(const QHostAddress &hostAddress, uint retries)
|
||||||
{
|
{
|
||||||
PingReply *reply = new PingReply(this);
|
PingReply *reply = createReply(hostAddress);
|
||||||
reply->m_targetHostAddress = hostAddress;
|
reply->m_retries = retries;
|
||||||
reply->m_networkInterface = NetworkUtils::getInterfaceForHostaddress(hostAddress);
|
|
||||||
|
// Perform the reply in the next event loop to give the user time to do the reply connects
|
||||||
|
m_replyQueue.enqueue(reply);
|
||||||
|
sendNextReply();
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
PingReply *Ping::ping(const QHostAddress &hostAddress, bool lookupHost, uint retries)
|
||||||
|
{
|
||||||
|
PingReply *reply = createReply(hostAddress);
|
||||||
|
reply->m_retries = retries;
|
||||||
|
reply->m_doHostLookup = lookupHost;
|
||||||
|
|
||||||
// Perform the reply in the next event loop to give the user time to do the reply connects
|
// Perform the reply in the next event loop to give the user time to do the reply connects
|
||||||
m_replyQueue.enqueue(reply);
|
m_replyQueue.enqueue(reply);
|
||||||
@ -133,7 +145,7 @@ void Ping::sendNextReply()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
PingReply *reply = m_replyQueue.dequeue();
|
PingReply *reply = m_replyQueue.dequeue();
|
||||||
//qCDebug(dcPing()) << "Send next reply," << m_replyQueue.count() << "left in queue";
|
qCDebug(dcPing()) << "Send next reply," << m_replyQueue.count() << "left in queue";
|
||||||
m_queueTimer->start();
|
m_queueTimer->start();
|
||||||
QTimer::singleShot(0, reply, [=]() { performPing(reply); });
|
QTimer::singleShot(0, reply, [=]() { performPing(reply); });
|
||||||
}
|
}
|
||||||
@ -168,11 +180,10 @@ void Ping::performPing(PingReply *reply)
|
|||||||
memset(&requestPacket, 0, sizeof(requestPacket));
|
memset(&requestPacket, 0, sizeof(requestPacket));
|
||||||
requestPacket.icmpHeadr.type = ICMP_ECHO;
|
requestPacket.icmpHeadr.type = ICMP_ECHO;
|
||||||
if (reply->requestId() == 0) {
|
if (reply->requestId() == 0) {
|
||||||
requestPacket.icmpHeadr.un.echo.id = calculateRequestId();
|
reply->m_requestId = calculateRequestId();
|
||||||
} else {
|
|
||||||
requestPacket.icmpHeadr.un.echo.id = reply->requestId();
|
|
||||||
}
|
}
|
||||||
requestPacket.icmpHeadr.un.echo.sequence = htons(reply->m_sequenceNumber++);
|
requestPacket.icmpHeadr.un.echo.id = htons(reply->requestId());
|
||||||
|
requestPacket.icmpHeadr.un.echo.sequence = htons(reply->sequenceNumber());
|
||||||
|
|
||||||
// Write the ICMP payload
|
// Write the ICMP payload
|
||||||
memset(&requestPacket.icmpPayload, ' ', sizeof(requestPacket.icmpPayload));
|
memset(&requestPacket.icmpPayload, ' ', sizeof(requestPacket.icmpPayload));
|
||||||
@ -187,13 +198,9 @@ void Ping::performPing(PingReply *reply)
|
|||||||
qCWarning(dcPing()) << "Failed to get start time for ping measurement" << strerror(errno);
|
qCWarning(dcPing()) << "Failed to get start time for ping measurement" << strerror(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
reply->m_requestId = requestPacket.icmpHeadr.un.echo.id;
|
|
||||||
reply->m_targetHostAddress = targetHostAddress;
|
|
||||||
reply->m_sequenceNumber = requestPacket.icmpHeadr.un.echo.sequence;
|
|
||||||
|
|
||||||
qCDebug(dcPingTraffic()) << "Send ICMP echo request" << reply->targetHostAddress().toString() << ICMP_PACKET_SIZE << "[Bytes]"
|
qCDebug(dcPingTraffic()) << "Send ICMP echo request" << reply->targetHostAddress().toString() << ICMP_PACKET_SIZE << "[Bytes]"
|
||||||
<< "ID:" << QString("0x%1").arg(requestPacket.icmpHeadr.un.echo.id, 4, 16, QChar('0'))
|
<< "ID:" << QString("0x%1").arg(reply->requestId(), 4, 16, QChar('0'))
|
||||||
<< "Sequence:" << htons(requestPacket.icmpHeadr.un.echo.sequence);
|
<< "Sequence:" << reply->sequenceNumber();
|
||||||
|
|
||||||
// Send packet to the target ip
|
// Send packet to the target ip
|
||||||
int bytesSent = sendto(m_socketDescriptor, &requestPacket, sizeof(requestPacket), 0, (struct sockaddr *)&pingAddress, sizeof(pingAddress));
|
int bytesSent = sendto(m_socketDescriptor, &requestPacket, sizeof(requestPacket), 0, (struct sockaddr *)&pingAddress, sizeof(pingAddress));
|
||||||
@ -206,10 +213,7 @@ void Ping::performPing(PingReply *reply)
|
|||||||
|
|
||||||
// Start reply timer and handle timeout
|
// Start reply timer and handle timeout
|
||||||
m_pendingReplies.insert(reply->requestId(), reply);
|
m_pendingReplies.insert(reply->requestId(), reply);
|
||||||
reply->m_timer->start(8000);
|
reply->m_timer->start(m_timeoutDuration);
|
||||||
connect(reply, &PingReply::timeout, this, [=](){
|
|
||||||
finishReply(reply, PingReply::ErrorTimeout);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ping::verifyErrno(int error)
|
void Ping::verifyErrno(int error)
|
||||||
@ -287,12 +291,66 @@ quint16 Ping::calculateRequestId()
|
|||||||
return requestId;
|
return requestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PingReply *Ping::createReply(const QHostAddress &hostAddress)
|
||||||
|
{
|
||||||
|
PingReply *reply = new PingReply(this);
|
||||||
|
reply->m_targetHostAddress = hostAddress;
|
||||||
|
reply->m_networkInterface = NetworkUtils::getInterfaceForHostaddress(hostAddress);
|
||||||
|
|
||||||
|
connect(reply, &PingReply::timeout, this, [=](){
|
||||||
|
// Note: this is not the ICMP timeout, here we actually got nothing from nobody...
|
||||||
|
finishReply(reply, PingReply::ErrorTimeout);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(reply, &PingReply::aborted, this, [=](){
|
||||||
|
finishReply(reply, PingReply::ErrorAborted);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(reply, &PingReply::finished, this, [=](){
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
// Cleanup any retry left over queue stuff
|
||||||
|
m_pendingReplies.remove(reply->requestId());
|
||||||
|
m_replyQueue.removeAll(reply);
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
void Ping::finishReply(PingReply *reply, PingReply::Error error)
|
void Ping::finishReply(PingReply *reply, PingReply::Error error)
|
||||||
{
|
{
|
||||||
reply->m_error = error;
|
// Check if we should retry
|
||||||
m_pendingReplies.remove(reply->requestId());
|
if (reply->m_retryCount >= reply->m_retries ||
|
||||||
emit reply->finished();
|
error == PingReply::ErrorNoError ||
|
||||||
reply->deleteLater();
|
error == PingReply::ErrorAborted ||
|
||||||
|
error == PingReply::ErrorInvalidHostAddress ||
|
||||||
|
error == PingReply::ErrorPermissionDenied) {
|
||||||
|
// No retry, we are done
|
||||||
|
reply->m_error = error;
|
||||||
|
reply->m_timer->stop();
|
||||||
|
m_pendingReplies.remove(reply->requestId());
|
||||||
|
emit reply->finished();
|
||||||
|
} else {
|
||||||
|
// Note: don't remove from m_pendingReplies to prevent
|
||||||
|
// double assignmet of request id's between 2 retries
|
||||||
|
reply->m_error = error;
|
||||||
|
reply->m_retryCount++;
|
||||||
|
reply->m_sequenceNumber++;
|
||||||
|
|
||||||
|
if (reply->m_retries > 1) {
|
||||||
|
qCDebug(dcPing()) << "Ping finished with error" << error << "Retry ping" << reply->targetHostAddress().toString() << reply->m_retryCount << "/" << reply->m_retries;
|
||||||
|
} else {
|
||||||
|
qCDebug(dcPing()) << "Ping finished with error" << error << "Retry ping" << reply->targetHostAddress().toString();
|
||||||
|
}
|
||||||
|
emit reply->retry(error, reply->retryCount());
|
||||||
|
|
||||||
|
// Note: will be restarted once actually sent trough the network
|
||||||
|
reply->m_timer->stop();
|
||||||
|
|
||||||
|
// Re-Enqueu the reply
|
||||||
|
m_replyQueue.enqueue(reply);
|
||||||
|
sendNextReply();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ping::onSocketReadyRead(int socketDescriptor)
|
void Ping::onSocketReadyRead(int socketDescriptor)
|
||||||
@ -323,16 +381,19 @@ void Ping::onSocketReadyRead(int socketDescriptor)
|
|||||||
<< "TTL" << ipHeader->ttl;
|
<< "TTL" << ipHeader->ttl;
|
||||||
|
|
||||||
struct icmp *responsePacket = reinterpret_cast<struct icmp *>(receiveBuffer + ipHeaderLength);
|
struct icmp *responsePacket = reinterpret_cast<struct icmp *>(receiveBuffer + ipHeaderLength);
|
||||||
|
quint16 icmpId = htons(responsePacket->icmp_id);
|
||||||
|
quint16 icmpSequnceNumber = htons(responsePacket->icmp_seq);
|
||||||
qCDebug(dcPingTraffic()) << "ICMP packt (Size:" << icmpPacketSize << "Bytes):"
|
qCDebug(dcPingTraffic()) << "ICMP packt (Size:" << icmpPacketSize << "Bytes):"
|
||||||
<< "Type" << responsePacket->icmp_type
|
<< "Type" << responsePacket->icmp_type
|
||||||
<< "Code:" << responsePacket->icmp_code
|
<< "Code:" << responsePacket->icmp_code
|
||||||
<< "ID:" << QString("0x%1").arg(responsePacket->icmp_id, 4, 16, QChar('0'))
|
<< "ID:" << QString("0x%1").arg(icmpId, 4, 16, QChar('0'))
|
||||||
<< "Sequence:" << responsePacket->icmp_seq;
|
<< "Sequence:" << icmpSequnceNumber;
|
||||||
|
|
||||||
if (responsePacket->icmp_type == ICMP_ECHOREPLY) {
|
if (responsePacket->icmp_type == ICMP_ECHOREPLY) {
|
||||||
PingReply *reply = m_pendingReplies.take(responsePacket->icmp_id);
|
|
||||||
|
PingReply *reply = m_pendingReplies.take(icmpId);
|
||||||
if (!reply) {
|
if (!reply) {
|
||||||
qCDebug(dcPing()) << "No pending reply for ping echo response with id" << QString("0x%1").arg(responsePacket->icmp_id, 4, 16, QChar('0')) << "Sequence:" << htons(responsePacket->icmp_seq) << "from" << senderAddress.toString();
|
qCDebug(dcPing()) << "No pending reply for ping echo response with id" << QString("0x%1").arg(icmpId, 4, 16, QChar('0')) << "Sequence:" << icmpSequnceNumber << "from" << senderAddress.toString();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,8 +405,8 @@ void Ping::onSocketReadyRead(int socketDescriptor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify sequence number
|
// Verify sequence number
|
||||||
if (responsePacket->icmp_seq != reply->sequenceNumber()) {
|
if (icmpSequnceNumber != reply->sequenceNumber()) {
|
||||||
qCWarning(dcPing()) << "Received echo reply with different sequence number" << htons(responsePacket->icmp_seq);
|
qCWarning(dcPing()) << "Received echo reply with different sequence number" << icmpSequnceNumber;
|
||||||
finishReply(reply, PingReply::ErrorInvalidResponse);
|
finishReply(reply, PingReply::ErrorInvalidResponse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -356,15 +417,21 @@ void Ping::onSocketReadyRead(int socketDescriptor)
|
|||||||
timeValueSubtract(&receiveTimeValue, &reply->m_startTime);
|
timeValueSubtract(&receiveTimeValue, &reply->m_startTime);
|
||||||
reply->m_duration = qRound((receiveTimeValue.tv_sec * 1000 + (double)receiveTimeValue.tv_usec / 1000) * 100) / 100.0;
|
reply->m_duration = qRound((receiveTimeValue.tv_sec * 1000 + (double)receiveTimeValue.tv_usec / 1000) * 100) / 100.0;
|
||||||
|
|
||||||
// Note: due to a Qt bug < 5.9 we need to use old SLOT style and cannot make use of lambda here
|
qCDebug(dcPing()) << "Received ICMP response" << reply->targetHostAddress().toString() << ICMP_PACKET_SIZE << "[Bytes]"
|
||||||
int lookupId = QHostInfo::lookupHost(senderAddress.toString(), this, SLOT(onHostLookupFinished(QHostInfo)));
|
<< "ID:" << QString("0x%1").arg(icmpId, 4, 16, QChar('0'))
|
||||||
m_pendingHostLookups.insert(lookupId, reply);
|
<< "Sequence:" << icmpSequnceNumber
|
||||||
|
|
||||||
qCDebug(dcPingTraffic()) << "Received ICMP response" << reply->targetHostAddress().toString() << ICMP_PACKET_SIZE << "[Bytes]"
|
|
||||||
<< "ID:" << QString("0x%1").arg(responsePacket->icmp_id, 4, 16, QChar('0'))
|
|
||||||
<< "Sequence:" << htons(responsePacket->icmp_seq)
|
|
||||||
<< "Time:" << reply->duration() << "[ms]";
|
<< "Time:" << reply->duration() << "[ms]";
|
||||||
|
|
||||||
|
if (reply->doHostLookup()) {
|
||||||
|
// Note: due to a Qt bug < 5.9 we need to use old SLOT style and cannot make use of lambda here
|
||||||
|
int lookupId = QHostInfo::lookupHost(senderAddress.toString(), this, SLOT(onHostLookupFinished(QHostInfo)));
|
||||||
|
m_pendingHostLookups.insert(lookupId, reply);
|
||||||
|
} else {
|
||||||
|
finishReply(reply, PingReply::ErrorNoError);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} else if (responsePacket->icmp_type == ICMP_DEST_UNREACH) {
|
} else if (responsePacket->icmp_type == ICMP_DEST_UNREACH) {
|
||||||
|
|
||||||
// Get the sending package
|
// Get the sending package
|
||||||
@ -382,22 +449,25 @@ void Ping::onSocketReadyRead(int socketDescriptor)
|
|||||||
<< "TTL" << ipHeader->ttl;
|
<< "TTL" << ipHeader->ttl;
|
||||||
|
|
||||||
struct icmp *nestedResponsePacket = reinterpret_cast<struct icmp *>(receiveBuffer + messageOffset + nestedIpHeaderLength);
|
struct icmp *nestedResponsePacket = reinterpret_cast<struct icmp *>(receiveBuffer + messageOffset + nestedIpHeaderLength);
|
||||||
|
icmpId = htons(nestedResponsePacket->icmp_id);
|
||||||
|
icmpSequnceNumber = htons(nestedResponsePacket->icmp_seq);
|
||||||
|
|
||||||
qCDebug(dcPingTraffic()) << "++ ICMP packt (Size:" << nestedIcmpPacketSize << "Bytes):"
|
qCDebug(dcPingTraffic()) << "++ ICMP packt (Size:" << nestedIcmpPacketSize << "Bytes):"
|
||||||
<< "Type" << nestedResponsePacket->icmp_type
|
<< "Type" << nestedResponsePacket->icmp_type
|
||||||
<< "Code:" << nestedResponsePacket->icmp_code
|
<< "Code:" << nestedResponsePacket->icmp_code
|
||||||
<< "ID:" << QString("0x%1").arg(nestedResponsePacket->icmp_id, 4, 16, QChar('0'))
|
<< "ID:" << QString("0x%1").arg(icmpId, 4, 16, QChar('0'))
|
||||||
<< "Sequence:" << nestedResponsePacket->icmp_seq;
|
<< "Sequence:" << icmpSequnceNumber;
|
||||||
|
|
||||||
qCDebug(dcPing()) << "ICMP destination unreachable" << nestedDestinationAddress.toString()
|
qCDebug(dcPing()) << "ICMP destination unreachable" << nestedDestinationAddress.toString()
|
||||||
<< "Code:" << nestedResponsePacket->icmp_code
|
<< "Code:" << nestedResponsePacket->icmp_code
|
||||||
<< "ID:" << QString("0x%1").arg(nestedResponsePacket->icmp_id, 4, 16, QChar('0'))
|
<< "ID:" << QString("0x%1").arg(icmpId, 4, 16, QChar('0'))
|
||||||
<< "Sequence:" << htons(nestedResponsePacket->icmp_seq);
|
<< "Sequence:" << icmpSequnceNumber;
|
||||||
|
|
||||||
PingReply *reply = m_pendingReplies.take(nestedResponsePacket->icmp_id);
|
PingReply *reply = m_pendingReplies.take(icmpId);
|
||||||
if (!reply) {
|
if (!reply) {
|
||||||
qCDebug(dcPingTraffic()) << "No pending reply for ping echo response unreachable with ID"
|
qCDebug(dcPingTraffic()) << "No pending reply for ping echo response unreachable with ID"
|
||||||
<< QString("0x%1").arg(nestedResponsePacket->icmp_id, 4, 16, QChar('0'))
|
<< QString("0x%1").arg(icmpId, 4, 16, QChar('0'))
|
||||||
<< "Sequence:" << htons(nestedResponsePacket->icmp_seq)
|
<< "Sequence:" << icmpSequnceNumber
|
||||||
<< "from" << nestedSenderAddress.toString() << "to" << nestedDestinationAddress.toString();
|
<< "from" << nestedSenderAddress.toString() << "to" << nestedDestinationAddress.toString();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,7 +62,8 @@ public:
|
|||||||
|
|
||||||
PingReply::Error error() const;
|
PingReply::Error error() const;
|
||||||
|
|
||||||
PingReply *ping(const QHostAddress &hostAddress);
|
PingReply *ping(const QHostAddress &hostAddress, uint retries = 3);
|
||||||
|
PingReply *ping(const QHostAddress &hostAddress, bool lookupHost, uint retries = 3);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void availableChanged(bool available);
|
void availableChanged(bool available);
|
||||||
@ -76,6 +77,7 @@ private:
|
|||||||
// Config
|
// Config
|
||||||
QByteArray m_payload = "ping from nymea";
|
QByteArray m_payload = "ping from nymea";
|
||||||
PingReply::Error m_error = PingReply::ErrorNoError;
|
PingReply::Error m_error = PingReply::ErrorNoError;
|
||||||
|
uint m_timeoutDuration = 5000;
|
||||||
|
|
||||||
// Socket
|
// Socket
|
||||||
QSocketNotifier *m_socketNotifier = nullptr;
|
QSocketNotifier *m_socketNotifier = nullptr;
|
||||||
@ -98,6 +100,7 @@ private:
|
|||||||
void timeValueSubtract(struct timeval *start, struct timeval *stop);
|
void timeValueSubtract(struct timeval *start, struct timeval *stop);
|
||||||
quint16 calculateRequestId();
|
quint16 calculateRequestId();
|
||||||
|
|
||||||
|
PingReply *createReply(const QHostAddress &hostAddress);
|
||||||
void finishReply(PingReply *reply, PingReply::Error error);
|
void finishReply(PingReply *reply, PingReply::Error error);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
@ -63,6 +63,16 @@ QNetworkInterface PingReply::networkInterface() const
|
|||||||
return m_networkInterface;
|
return m_networkInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint PingReply::retries() const
|
||||||
|
{
|
||||||
|
return m_retries;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint PingReply::retryCount() const
|
||||||
|
{
|
||||||
|
return m_retryCount;
|
||||||
|
}
|
||||||
|
|
||||||
double PingReply::duration() const
|
double PingReply::duration() const
|
||||||
{
|
{
|
||||||
return m_duration;
|
return m_duration;
|
||||||
@ -72,3 +82,15 @@ PingReply::Error PingReply::error() const
|
|||||||
{
|
{
|
||||||
return m_error;
|
return m_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PingReply::doHostLookup() const
|
||||||
|
{
|
||||||
|
return m_doHostLookup;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PingReply::abort()
|
||||||
|
{
|
||||||
|
m_timer->stop();
|
||||||
|
m_error = ErrorAborted;
|
||||||
|
emit aborted();
|
||||||
|
}
|
||||||
|
|||||||
@ -51,6 +51,7 @@ class LIBNYMEA_EXPORT PingReply : public QObject
|
|||||||
public:
|
public:
|
||||||
enum Error {
|
enum Error {
|
||||||
ErrorNoError,
|
ErrorNoError,
|
||||||
|
ErrorAborted,
|
||||||
ErrorInvalidResponse,
|
ErrorInvalidResponse,
|
||||||
ErrorNetworkDown,
|
ErrorNetworkDown,
|
||||||
ErrorNetworkUnreachable,
|
ErrorNetworkUnreachable,
|
||||||
@ -70,22 +71,36 @@ public:
|
|||||||
QString hostName() const;
|
QString hostName() const;
|
||||||
QNetworkInterface networkInterface() const;
|
QNetworkInterface networkInterface() const;
|
||||||
|
|
||||||
|
uint retries() const;
|
||||||
|
uint retryCount() const;
|
||||||
|
|
||||||
double duration() const;
|
double duration() const;
|
||||||
|
|
||||||
Error error() const;
|
Error error() const;
|
||||||
|
|
||||||
|
bool doHostLookup() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void abort();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finished();
|
void finished();
|
||||||
void timeout();
|
void timeout();
|
||||||
|
void retry(Error error, uint retryCount);
|
||||||
|
void aborted();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTimer *m_timer = nullptr;
|
QTimer *m_timer = nullptr;
|
||||||
QHostAddress m_targetHostAddress;
|
QHostAddress m_targetHostAddress;
|
||||||
quint16 m_sequenceNumber = 0;
|
quint16 m_sequenceNumber = 1;
|
||||||
quint16 m_requestId = 0;
|
quint16 m_requestId = 0;
|
||||||
QString m_hostName;
|
QString m_hostName;
|
||||||
QNetworkInterface m_networkInterface;
|
QNetworkInterface m_networkInterface;
|
||||||
|
|
||||||
|
bool m_doHostLookup = false;
|
||||||
|
|
||||||
|
uint m_retries = 0;
|
||||||
|
uint m_retryCount = 0;
|
||||||
uint m_timeout = 3;
|
uint m_timeout = 3;
|
||||||
double m_duration = 0;
|
double m_duration = 0;
|
||||||
Error m_error = ErrorNoError;
|
Error m_error = ErrorNoError;
|
||||||
|
|||||||
Reference in New Issue
Block a user