X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/085c36723242f7bd1e0fd9bf49b950da6cb96039..0c097ef3435d2a45c1ee4ac80f8bd3f254fb8df5:/libs/pinger/pinger.cpp diff --git a/libs/pinger/pinger.cpp b/libs/pinger/pinger.cpp index 042edcba..59937b1c 100644 --- a/libs/pinger/pinger.cpp +++ b/libs/pinger/pinger.cpp @@ -1,13 +1,8 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "stg/pinger.h" + +#include "stg/common.h" +#include #include #include #include @@ -15,318 +10,259 @@ #include #include -#include "stg/common.h" -#include "stg/locker.h" - -#include "stg/pinger.h" +#include +#include +#include +#include +#include +#include +#include +#include #ifdef STG_TIME extern volatile time_t stgTime; #endif //----------------------------------------------------------------------------- -STG_PINGER::STG_PINGER(time_t d) +STG_PINGER::STG_PINGER(unsigned d) : m_delay(d), - m_nonstop(false), m_isRunningRecver(false), m_isRunningSender(false), m_sendSocket(-1), m_recvSocket(-1), m_pid(0) { -pthread_mutex_init(&m_mutex, NULL); -memset(&m_pmSend, 0, sizeof(m_pmSend)); + memset(&m_pmSend, 0, sizeof(m_pmSend)); } //----------------------------------------------------------------------------- -STG_PINGER::~STG_PINGER() +bool STG_PINGER::Start() { -pthread_mutex_destroy(&m_mutex); -} -//----------------------------------------------------------------------------- -int STG_PINGER::Start() -{ -struct protoent *proto = NULL; -proto = getprotobyname("ICMP"); -m_sendSocket = socket(PF_INET, SOCK_RAW, proto->p_proto); -m_recvSocket = socket(PF_INET, SOCK_RAW, proto->p_proto); -m_nonstop = true; -m_pid = static_cast(getpid()) % 65535; -if (m_sendSocket < 0 || m_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(getpid()) % 65535; + if (m_sendSocket < 0 || m_recvSocket < 0) { - m_errorStr = "Cannot create socket."; - return -1; + m_errorStr = "Cannot create socket."; + return false; } -if (pthread_create(&m_sendThread, NULL, RunSendPing, this)) - { - m_errorStr = "Cannot create send thread."; - return -1; - } - -if (pthread_create(&m_recvThread, NULL, RunRecvPing, this)) - { - m_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(m_recvSocket); -m_nonstop = false; -if (m_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 (!m_isRunningRecver) - break; + if (!m_isRunningRecver) + break; - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); } } -if (m_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 (!m_isRunningSender) - break; + if (!m_isRunningSender) + break; - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); } } -close(m_sendSocket); + close(m_sendSocket); -if (m_isRunningSender || m_isRunningRecver) - return -1; - -return 0; + return !m_isRunningSender && !m_isRunningRecver; } //----------------------------------------------------------------------------- void STG_PINGER::AddIP(uint32_t ip) { -STG_LOCKER lock(&m_mutex); -m_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) { -STG_LOCKER lock(&m_mutex); -m_ipToDel.push_back(ip); -} -//----------------------------------------------------------------------------- -void STG_PINGER::RealAddIP() -{ -STG_LOCKER lock(&m_mutex); - -auto iter = m_ipToAdd.begin(); -while (iter != m_ipToAdd.end()) - { - m_pingIP.insert(std::make_pair(*iter, 0)); - ++iter; - } -m_ipToAdd.erase(m_ipToAdd.begin(), m_ipToAdd.end()); -} -//----------------------------------------------------------------------------- -void STG_PINGER::RealDelIP() -{ -STG_LOCKER lock(&m_mutex); - -auto iter = m_ipToDel.begin(); -while (iter != m_ipToDel.end()) - { - auto treeIter = m_pingIP.find(*iter); - if (treeIter != m_pingIP.end()) - m_pingIP.erase(treeIter); - - ++iter; - } -m_ipToDel.erase(m_ipToDel.begin(), m_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() { -STG_LOCKER lock(&m_mutex); -auto iter = m_pingIP.begin(); -while (iter != m_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(&m_mutex); + std::lock_guard lock(m_mutex); -auto treeIter = m_pingIP.find(ip); -if (treeIter == m_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(data); -uint32_t sum = 0; -uint32_t result; + const auto* buf = static_cast(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(buf); + if ( len == 1 ) + sum += *reinterpret_cast(buf); -sum = (sum >> 16) + (sum & 0xFFFF); -sum += (sum >> 16); -result = ~sum; -return static_cast(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(&m_pmSend, 0, sizeof(m_pmSend)); -m_pmSend.hdr.type = ICMP_ECHO; -m_pmSend.hdr.un.echo.id = static_cast(m_pid); -memcpy(m_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(m_pid); + memcpy(m_pmSend.msg, &ip, sizeof(ip)); -m_pmSend.hdr.checksum = PingCheckSum(&m_pmSend, sizeof(m_pmSend)); + m_pmSend.hdr.checksum = PingCheckSum(&m_pmSend, sizeof(m_pmSend)); -if (sendto(m_sendSocket, &m_pmSend, sizeof(m_pmSend), 0, reinterpret_cast(&addr), sizeof(addr)) <= 0 ) + if (sendto(m_sendSocket, &m_pmSend, sizeof(m_pmSend), 0, reinterpret_cast(&addr), sizeof(addr)) <= 0 ) { - m_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() { -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(m_recvSocket, &buf, sizeof(buf), 0, reinterpret_cast(&addr), &len)) + if (recvfrom(m_recvSocket, &buf, sizeof(buf), 0, reinterpret_cast(&addr), &len)) { - struct IP_HDR * ip = static_cast(static_cast(buf)); - struct ICMP_HDR *icmp = static_cast(static_cast(buf + ip->ihl * 4)); + auto* ip = static_cast(static_cast(buf)); + auto* icmp = static_cast(static_cast(buf + ip->ihl * 4)); - if (icmp->un.echo.id != m_pid) - return 0; + if (icmp->un.echo.id != m_pid) + return 0; - ipAddr = *static_cast(static_cast(buf + sizeof(ICMP_HDR) + ip->ihl * 4)); + ipAddr = *static_cast(static_cast(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); - -auto* pinger = static_cast(d); + sigset_t signalSet; + sigfillset(&signalSet); + pthread_sigmask(SIG_BLOCK, &signalSet, NULL); -pinger->m_isRunningSender = true; -time_t lastPing = 0; -while (pinger->m_nonstop) + m_isRunningSender = true; + time_t lastPing = 0; + while (!token.stop_requested()) { - pinger->RealAddIP(); - pinger->RealDelIP(); - - std::multimap::iterator iter; - iter = pinger->m_pingIP.begin(); - while (iter != pinger->m_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->m_delay && pinger->m_nonstop) - { #ifdef STG_TIME + lastPing = stgTime; currTime = stgTime; #else - currTime = time(NULL); + currTime = lastPing = time(NULL); #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->m_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); - -auto* pinger = static_cast(d); + sigset_t signalSet; + sigfillset(&signalSet); + pthread_sigmask(SIG_BLOCK, &signalSet, NULL); -pinger->m_isRunningRecver = true; + m_isRunningRecver = true; -while (pinger->m_nonstop) + while (!token.stop_requested()) { - uint32_t ip = pinger->RecvPing(); + uint32_t ip = RecvPing(); - if (ip) + if (ip) { - auto treeIterUpper = pinger->m_pingIP.upper_bound(ip); - auto treeIterLower = pinger->m_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->m_isRunningRecver = false; -return NULL; + m_isRunningRecver = false; } //-----------------------------------------------------------------------------