]> git.stg.codes - stg.git/blobdiff - libs/pinger/pinger.cpp
Add an option to opt-out Firebird store.
[stg.git] / libs / pinger / pinger.cpp
index 07415812a6bbf61f831b9f797cb16fbad8573f9f..59937b1c7b92375d98503656d2964622a0bf6955 100644 (file)
@@ -1,13 +1,8 @@
-#include <pthread.h>
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <fcntl.h>
+#include "stg/pinger.h"
+
+#include "stg/common.h"
 
 
+#include <chrono>
 #include <cstdlib>
 #include <csignal>
 #include <cstring>
 #include <cstdlib>
 #include <csignal>
 #include <cstring>
 #include <cmath>
 #include <cstdio>
 
 #include <cmath>
 #include <cstdio>
 
-#include "stg/common.h"
-#include "stg/locker.h"
-
-#include "stg/pinger.h"
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #ifdef STG_TIME
 extern volatile time_t stgTime;
 #endif
 
 //-----------------------------------------------------------------------------
 
 #ifdef STG_TIME
 extern volatile time_t stgTime;
 #endif
 
 //-----------------------------------------------------------------------------
-STG_PINGER::STG_PINGER(time_t d)
-    : delay(d),
-      nonstop(false),
-      isRunningRecver(false),
-      isRunningSender(false),
-      sendSocket(-1),
-      recvSocket(-1),
-      sendThread(),
-      recvThread(),
-      pmSend(),
-      pid(0),
-      errorStr(),
-      pingIP(),
-      ipToAdd(),
-      ipToDel(),
-      mutex()
+STG_PINGER::STG_PINGER(unsigned d)
+    : m_delay(d),
+      m_isRunningRecver(false),
+      m_isRunningSender(false),
+      m_sendSocket(-1),
+      m_recvSocket(-1),
+      m_pid(0)
 {
 {
-pthread_mutex_init(&mutex, NULL);
-memset(&pmSend, 0, sizeof(pmSend));
+    memset(&m_pmSend, 0, sizeof(m_pmSend));
 }
 //-----------------------------------------------------------------------------
 }
 //-----------------------------------------------------------------------------
-STG_PINGER::~STG_PINGER()
+bool STG_PINGER::Start()
 {
 {
-pthread_mutex_destroy(&mutex);
-}
-//-----------------------------------------------------------------------------
-int STG_PINGER::Start()
-{
-struct protoent *proto = NULL;
-proto = getprotobyname("ICMP");
-sendSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
-recvSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
-nonstop = true;
-pid = (int) getpid() % 65535;
-if (sendSocket < 0 || recvSocket < 0)
+    auto* proto = getprotobyname("ICMP");
+    m_sendSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
+    m_recvSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
+    m_pid = static_cast<uint32_t>(getpid()) % 65535;
+    if (m_sendSocket < 0 || m_recvSocket < 0)
     {
     {
-    errorStr = "Cannot create socket.";
-    return -1;
+        m_errorStr = "Cannot create socket.";
+        return false;
     }
 
     }
 
-if (pthread_create(&sendThread, NULL, RunSendPing, this))
-    {
-    errorStr = "Cannot create send thread.";
-    return -1;
-    }
-
-if (pthread_create(&recvThread, NULL, RunRecvPing, this))
-    {
-    errorStr = "Cannot create recv thread.";
-    return -1;
-    }
+    m_sendThread = std::jthread([this](auto token){ RunSendPing(std::move(token)); });
+    m_recvThread = std::jthread([this](auto token){ RunRecvPing(std::move(token)); });
 
 
-return 0;
+    return true;
 }
 //-----------------------------------------------------------------------------
 }
 //-----------------------------------------------------------------------------
-int STG_PINGER::Stop()
+bool STG_PINGER::Stop()
 {
 {
-close(recvSocket);
-nonstop = false;
-if (isRunningRecver)
+    close(m_recvSocket);
+    m_sendThread.request_stop();
+    if (m_isRunningRecver)
     {
     {
-    //5 seconds to thread stops itself
-    for (size_t i = 0; i < 25; i++)
+        //5 seconds to thread stops itself
+        for (size_t i = 0; i < 25; i++)
         {
         {
-        if (i % 5 == 0)
-            SendPing(0x0100007f);//127.0.0.1
+            if (i % 5 == 0)
+                SendPing(0x0100007f);//127.0.0.1
 
 
-        if (!isRunningRecver)
-            break;
+            if (!m_isRunningRecver)
+                break;
 
 
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
+            std::this_thread::sleep_for(std::chrono::milliseconds(200));
         }
     }
 
         }
     }
 
-if (isRunningSender)
+    if (m_isRunningSender)
     {
     {
-    //5 seconds to thread stops itself
-    for (size_t i = 0; i < 25; i++)
+        //5 seconds to thread stops itself
+        for (size_t i = 0; i < 25; i++)
         {
         {
-        if (!isRunningSender)
-            break;
+            if (!m_isRunningSender)
+                break;
 
 
-        struct timespec ts = {0, 200000000};
-        nanosleep(&ts, NULL);
+            std::this_thread::sleep_for(std::chrono::milliseconds(200));
         }
     }
 
         }
     }
 
-close(sendSocket);
+    close(m_sendSocket);
 
 
-if (isRunningSender || isRunningRecver)
-    return -1;
-
-return 0;
+    return !m_isRunningSender && !m_isRunningRecver;
 }
 //-----------------------------------------------------------------------------
 void STG_PINGER::AddIP(uint32_t ip)
 {
 }
 //-----------------------------------------------------------------------------
 void STG_PINGER::AddIP(uint32_t ip)
 {
-STG_LOCKER lock(&mutex);
-ipToAdd.push_back(ip);
+    std::lock_guard lock(m_mutex);
+    m_pingIPs.insert(std::make_pair(ip, 0));
 }
 //-----------------------------------------------------------------------------
 void STG_PINGER::DelIP(uint32_t ip)
 {
 }
 //-----------------------------------------------------------------------------
 void STG_PINGER::DelIP(uint32_t ip)
 {
-STG_LOCKER lock(&mutex);
-ipToDel.push_back(ip);
-}
-//-----------------------------------------------------------------------------
-void STG_PINGER::RealAddIP()
-{
-STG_LOCKER lock(&mutex);
-
-std::list<uint32_t>::iterator iter;
-iter = ipToAdd.begin();
-while (iter != ipToAdd.end())
-    {
-    pingIP.insert(std::make_pair(*iter, 0));
-    ++iter;
-    }
-ipToAdd.erase(ipToAdd.begin(), ipToAdd.end());
-}
-//-----------------------------------------------------------------------------
-void STG_PINGER::RealDelIP()
-{
-STG_LOCKER lock(&mutex);
-
-std::list<uint32_t>::iterator iter;
-std::multimap<uint32_t, time_t>::iterator treeIter;
-iter = ipToDel.begin();
-while (iter != ipToDel.end())
-    {
-    treeIter = pingIP.find(*iter);
-    if (treeIter != pingIP.end())
-        pingIP.erase(treeIter);
-
-    ++iter;
-    }
-ipToDel.erase(ipToDel.begin(), ipToDel.end());
+    std::lock_guard lock(m_mutex);
+    auto it = m_pingIPs.find(ip);
+    if (it != m_pingIPs.end())
+        m_pingIPs.erase(it);
 }
 //-----------------------------------------------------------------------------
 void STG_PINGER::PrintAllIP()
 {
 }
 //-----------------------------------------------------------------------------
 void STG_PINGER::PrintAllIP()
 {
-STG_LOCKER lock(&mutex);
-std::multimap<uint32_t, time_t>::iterator iter;
-iter = pingIP.begin();
-while (iter != pingIP.end())
+    std::lock_guard lock(m_mutex);
+    for (auto kv : m_pingIPs)
     {
     {
-    uint32_t ip = iter->first;
-    time_t t = iter->second;
-    std::string s = std::to_string(t);
-    printf("ip = %s, time = %9s\n", inet_ntostring(ip).c_str(), s.c_str());
-    ++iter;
+        uint32_t ip = kv.first;
+        time_t t = kv.second;
+        std::string s = std::to_string(t);
+        printf("ip = %s, time = %9s\n", inet_ntostring(ip).c_str(), s.c_str());
     }
     }
-
 }
 //-----------------------------------------------------------------------------
 }
 //-----------------------------------------------------------------------------
-int STG_PINGER::GetIPTime(uint32_t ip, time_t * t) const
+bool STG_PINGER::GetIPTime(uint32_t ip, time_t& t) const
 {
 {
-STG_LOCKER lock(&mutex);
-std::multimap<uint32_t, time_t>::const_iterator treeIter;
+    std::lock_guard lock(m_mutex);
 
 
-treeIter = pingIP.find(ip);
-if (treeIter == pingIP.end())
-    return -1;
+    auto it = m_pingIPs.find(ip);
+    if (it == m_pingIPs.end())
+        return false;
 
 
-*t = treeIter->second;
-return 0;
+    t = it->second;
+    return true;
 }
 //-----------------------------------------------------------------------------
 }
 //-----------------------------------------------------------------------------
-uint16_t STG_PINGER::PingCheckSum(void * data, int len)
+uint16_t STG_PINGER::PingCheckSum(const void* data, int len)
 {
 {
-uint16_t * buf = static_cast<uint16_t *>(data);
-uint32_t sum = 0;
-uint32_t result;
+    const auto* buf = static_cast<const uint16_t*>(data);
+    uint32_t sum = 0;
 
 
-for ( sum = 0; len > 1; len -= 2 )
-    sum += *buf++;
+    for ( sum = 0; len > 1; len -= 2 )
+        sum += *buf++;
 
 
-if ( len == 1 )
-    sum += *reinterpret_cast<uint8_t*>(buf);
+    if ( len == 1 )
+        sum += *reinterpret_cast<const uint8_t*>(buf);
 
 
-sum = (sum >> 16) + (sum & 0xFFFF);
-sum += (sum >> 16);
-result = ~sum;
-return static_cast<uint16_t>(result);
+    sum = (sum >> 16) + (sum & 0xFFFF);
+    sum += (sum >> 16);
+
+    return ~sum;
 }
 //-----------------------------------------------------------------------------
 }
 //-----------------------------------------------------------------------------
-int STG_PINGER::SendPing(uint32_t ip)
+bool STG_PINGER::SendPing(uint32_t ip)
 {
 {
-struct sockaddr_in addr;
-memset(&addr, 0, sizeof(addr));
-addr.sin_family = AF_INET;
-addr.sin_port = 0;
-addr.sin_addr.s_addr = ip;
+    struct sockaddr_in addr;
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = 0;
+    addr.sin_addr.s_addr = ip;
 
 
-memset(&pmSend, 0, sizeof(pmSend));
-pmSend.hdr.type = ICMP_ECHO;
-pmSend.hdr.un.echo.id = static_cast<uint16_t>(pid);
-memcpy(pmSend.msg, &ip, sizeof(ip));
+    memset(&m_pmSend, 0, sizeof(m_pmSend));
+    m_pmSend.hdr.type = ICMP_ECHO;
+    m_pmSend.hdr.un.echo.id = static_cast<uint16_t>(m_pid);
+    memcpy(m_pmSend.msg, &ip, sizeof(ip));
 
 
-pmSend.hdr.checksum = PingCheckSum(&pmSend, sizeof(pmSend));
+    m_pmSend.hdr.checksum = PingCheckSum(&m_pmSend, sizeof(m_pmSend));
 
 
-if (sendto(sendSocket, &pmSend, sizeof(pmSend), 0, (sockaddr *)&addr, sizeof(addr)) <= 0 )
+    if (sendto(m_sendSocket, &m_pmSend, sizeof(m_pmSend), 0, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) <= 0 )
     {
     {
-    errorStr = "Send ping error: " + std::string(strerror(errno));
-    return -1;
+        m_errorStr = "Send ping error: " + std::string(strerror(errno));
+        return false;
     }
 
 
     }
 
 
-return 0;
+    return true;
 }
 //-----------------------------------------------------------------------------
 uint32_t STG_PINGER::RecvPing()
 {
 }
 //-----------------------------------------------------------------------------
 uint32_t STG_PINGER::RecvPing()
 {
-struct sockaddr_in addr;
-uint32_t ipAddr = 0;
+    struct sockaddr_in addr;
+    uint32_t ipAddr = 0;
 
 
-char buf[128];
-memset(buf, 0, sizeof(buf));
-socklen_t len = sizeof(addr);
+    uint8_t buf[128];
+    memset(buf, 0, sizeof(buf));
+    socklen_t len = sizeof(addr);
 
 
-if (recvfrom(recvSocket, &buf, sizeof(buf), 0, reinterpret_cast<struct sockaddr*>(&addr), &len))
+    if (recvfrom(m_recvSocket, &buf, sizeof(buf), 0, reinterpret_cast<struct sockaddr*>(&addr), &len))
     {
     {
-    struct IP_HDR * ip = static_cast<struct IP_HDR *>(static_cast<void *>(buf));
-    struct ICMP_HDR *icmp = static_cast<struct ICMP_HDR *>(static_cast<void *>(buf + ip->ihl * 4));
+        auto* ip = static_cast<struct IP_HDR *>(static_cast<void *>(buf));
+        auto* icmp = static_cast<struct ICMP_HDR *>(static_cast<void *>(buf + ip->ihl * 4));
 
 
-    if (icmp->un.echo.id != pid)
-        return 0;
+        if (icmp->un.echo.id != m_pid)
+            return 0;
 
 
-    ipAddr = *static_cast<uint32_t*>(static_cast<void *>(buf + sizeof(ICMP_HDR) + ip->ihl * 4));
+        ipAddr = *static_cast<uint32_t*>(static_cast<void *>(buf + sizeof(ICMP_HDR) + ip->ihl * 4));
     }
 
     }
 
-return ipAddr;
+    return ipAddr;
 }
 //-----------------------------------------------------------------------------
 }
 //-----------------------------------------------------------------------------
-void * STG_PINGER::RunSendPing(void * d)
+void STG_PINGER::RunSendPing(std::stop_token token)
 {
 {
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-STG_PINGER * pinger = static_cast<STG_PINGER *>(d);
+    sigset_t signalSet;
+    sigfillset(&signalSet);
+    pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
 
 
-pinger->isRunningSender = true;
-time_t lastPing = 0;
-while (pinger->nonstop)
+    m_isRunningSender = true;
+    time_t lastPing = 0;
+    while (!token.stop_requested())
     {
     {
-    pinger->RealAddIP();
-    pinger->RealDelIP();
-
-    std::multimap<uint32_t, time_t>::iterator iter;
-    iter = pinger->pingIP.begin();
-    while (iter != pinger->pingIP.end())
+        PingIPs ips;
         {
         {
-        pinger->SendPing(iter->first);
-        ++iter;
+            std::lock_guard lock(m_mutex);
+            ips = m_pingIPs;
         }
 
         }
 
-    time_t currTime;
+        for (const auto& kv : ips)
+            SendPing(kv.first);
 
 
-    #ifdef STG_TIME
-    lastPing = stgTime;
-    currTime = stgTime;
-    #else
-    currTime = lastPing = time(NULL);
-    #endif
+        time_t currTime;
 
 
-    while (currTime - lastPing < pinger->delay && pinger->nonstop)
-        {
         #ifdef STG_TIME
         #ifdef STG_TIME
+        lastPing = stgTime;
         currTime = stgTime;
         #else
         currTime = stgTime;
         #else
-        currTime = time(NULL);
+        currTime = lastPing = time(NULL);
         #endif
         #endif
-        struct timespec ts = {0, 20000000};
-        nanosleep(&ts, NULL);
+
+        while (currTime - lastPing < m_delay && !token.stop_requested())
+        {
+            #ifdef STG_TIME
+            currTime = stgTime;
+            #else
+            currTime = time(NULL);
+            #endif
+            std::this_thread::sleep_for(std::chrono::milliseconds(200));
         }
     }
 
         }
     }
 
-pinger->isRunningSender = false;
-
-return NULL;
+    m_isRunningSender = false;
 }
 //-----------------------------------------------------------------------------
 }
 //-----------------------------------------------------------------------------
-void * STG_PINGER::RunRecvPing(void * d)
+void STG_PINGER::RunRecvPing(std::stop_token token)
 {
 {
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-STG_PINGER * pinger = static_cast<STG_PINGER *>(d);
+    sigset_t signalSet;
+    sigfillset(&signalSet);
+    pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
 
 
-pinger->isRunningRecver = true;
+    m_isRunningRecver = true;
 
 
-while (pinger->nonstop)
+    while (!token.stop_requested())
     {
     {
-    uint32_t ip = pinger->RecvPing();
+        uint32_t ip = RecvPing();
 
 
-    if (ip)
+        if (ip)
         {
         {
-        std::multimap<uint32_t, time_t>::iterator treeIterUpper = pinger->pingIP.upper_bound(ip);
-        std::multimap<uint32_t, time_t>::iterator treeIterLower = pinger->pingIP.lower_bound(ip);
-        while (treeIterUpper != treeIterLower)
+            std::lock_guard lock(m_mutex);
+            auto treeIterUpper = m_pingIPs.upper_bound(ip);
+            auto treeIterLower = m_pingIPs.lower_bound(ip);
+            while (treeIterUpper != treeIterLower)
             {
             {
-            #ifdef STG_TIME
-            treeIterLower->second = stgTime;
-            #else
-            treeIterLower->second = time(NULL);
-            #endif
-            ++treeIterLower;
+                #ifdef STG_TIME
+                treeIterLower->second = stgTime;
+                #else
+                treeIterLower->second = time(NULL);
+                #endif
+                ++treeIterLower;
             }
         }
 
     }
             }
         }
 
     }
-pinger->isRunningRecver = false;
-return NULL;
+    m_isRunningRecver = false;
 }
 //-----------------------------------------------------------------------------
 }
 //-----------------------------------------------------------------------------