#include "stg/common.h"
#include "stg/ia.h"
+#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <cstring>
//---------------------------------------------------------------------------
#ifndef WIN32
#include <sys/time.h>
-void Sleep(int ms)
-{
-long long res = ms * 1000000;
-struct timespec ts = {res / 1000000000, res % 1000000000};
-nanosleep(&ts, NULL);
-}
-//---------------------------------------------------------------------------
-void * RunL(void * data)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-auto* c = static_cast<IA_CLIENT_PROT*>(data);
-static int a = 0;
-
-if (a == 0)
- {
- Sleep(50);
- a = 1;
- }
-
-while (c->GetNonstop())
- {
- c->Run();
- }
-return NULL;
-}
//---------------------------------------------------------------------------
long GetTickCount()
{
gettimeofday(&tv, NULL);
return tv.tv_sec*1000 + tv.tv_usec/1000;
}
-#else
-//---------------------------------------------------------------------------
-unsigned long WINAPI RunW(void * data)
-{
-auto* c = static_cast<IA_CLIENT_PROT*>(data);
-while (c->GetNonstop())
- c->Run();
-return 0;
-}
-//---------------------------------------------------------------------------
#endif
+//---------------------------------------------------------------------------
namespace
{
m_phase(1),
m_phaseTime(0),
m_codeError(0),
- m_nonstop(false),
m_isNetPrepared(false),
m_proxyMode(false),
m_serverName(sn),
//---------------------------------------------------------------------------
void IA_CLIENT_PROT::Start()
{
-m_nonstop = true;
-#ifdef WIN32
-unsigned long pt;
-CreateThread(NULL, 16384, RunW, this, 0, &pt);
-#else
-pthread_create(&m_thread, NULL, RunL, this);
-#endif
+ m_thread = std::jthread([this](auto token){ Run(std::move(token)); });
}
//---------------------------------------------------------------------------
void IA_CLIENT_PROT::Stop()
{
-m_nonstop = false;
+ if (m_thread.joinable())
+ m_thread.request_stop();
}
//---------------------------------------------------------------------------
-void IA_CLIENT_PROT::Run()
+void IA_CLIENT_PROT::Run(std::stop_token token)
{
-NetRecv();
-
-switch (m_phase)
+ while (!token.stop_requested())
{
- case 1:
- if (m_action == IA_CONNECT)
- {
- m_action = IA_NONE;
- NetSend(CONN_SYN_N);
- m_phase = 2;
- m_phaseTime = GetTickCount();
- }
- if (m_reconnect && !m_firstConnect)
- {
- m_action = IA_CONNECT;
- }
- break;
-
- case 2:
- if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
- {
- m_phase = 1;
- m_phaseTime = GetTickCount();
- if (m_pStatusChangedCb != NULL)
- m_pStatusChangedCb(0, m_statusChangedCbData);
- }
-
- if (m_action == IA_DISCONNECT)
- {
- m_action = IA_NONE;
- NetSend(DISCONN_SYN_N);
- m_phase = 4;
- m_phaseTime = GetTickCount();
- }
-
- break;
-
- case 3:
- if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_userTimeout)
- {
- m_phase = 1;
- m_phaseTime = GetTickCount();
- if (m_pStatusChangedCb != NULL)
- m_pStatusChangedCb(0, m_statusChangedCbData);
- m_firstConnect = false;
- }
-
- if (m_action == IA_DISCONNECT)
- {
- m_action = IA_NONE;
- NetSend(DISCONN_SYN_N);
- m_phase = 4;
- m_phaseTime = GetTickCount();
- }
+ NetRecv();
- break;
-
- case 4:
- if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
- {
- m_phase=1;
- m_phaseTime = GetTickCount();
- if (m_pStatusChangedCb != NULL)
- m_pStatusChangedCb(0, m_statusChangedCbData);
- }
-
- if (m_action == IA_CONNECT)
- {
- m_action = IA_NONE;
- NetSend(CONN_SYN_N);
- m_phase = 2;
- m_phaseTime = GetTickCount();
- }
-
- break;
-
- case 5:
- if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
- {
- m_phase = 1;
- m_phaseTime = GetTickCount();
- if (m_pStatusChangedCb != NULL)
- m_pStatusChangedCb(0, m_statusChangedCbData);
- }
-
- if (m_action == IA_CONNECT)
- {
- m_action = IA_NONE;
- NetSend(CONN_SYN_N);
- m_phase = 2;
- m_phaseTime = GetTickCount();
- }
-
- break;
+ switch (m_phase)
+ {
+ case 1:
+ if (m_action == IA_CONNECT)
+ {
+ m_action = IA_NONE;
+ NetSend(CONN_SYN_N);
+ m_phase = 2;
+ m_phaseTime = GetTickCount();
+ }
+ if (m_reconnect && !m_firstConnect)
+ {
+ m_action = IA_CONNECT;
+ }
+ break;
+
+ case 2:
+ if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
+ {
+ m_phase = 1;
+ m_phaseTime = GetTickCount();
+ if (m_pStatusChangedCb != NULL)
+ m_pStatusChangedCb(0, m_statusChangedCbData);
+ }
+
+ if (m_action == IA_DISCONNECT)
+ {
+ m_action = IA_NONE;
+ NetSend(DISCONN_SYN_N);
+ m_phase = 4;
+ m_phaseTime = GetTickCount();
+ }
+
+ break;
+
+ case 3:
+ if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_userTimeout)
+ {
+ m_phase = 1;
+ m_phaseTime = GetTickCount();
+ if (m_pStatusChangedCb != NULL)
+ m_pStatusChangedCb(0, m_statusChangedCbData);
+ m_firstConnect = false;
+ }
+
+ if (m_action == IA_DISCONNECT)
+ {
+ m_action = IA_NONE;
+ NetSend(DISCONN_SYN_N);
+ m_phase = 4;
+ m_phaseTime = GetTickCount();
+ }
+
+ break;
+
+ case 4:
+ if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
+ {
+ m_phase=1;
+ m_phaseTime = GetTickCount();
+ if (m_pStatusChangedCb != NULL)
+ m_pStatusChangedCb(0, m_statusChangedCbData);
+ }
+
+ if (m_action == IA_CONNECT)
+ {
+ m_action = IA_NONE;
+ NetSend(CONN_SYN_N);
+ m_phase = 2;
+ m_phaseTime = GetTickCount();
+ }
+
+ break;
+
+ case 5:
+ if (static_cast<int>(GetTickCount() - m_phaseTime)/1000 > m_aliveTimeout)
+ {
+ m_phase = 1;
+ m_phaseTime = GetTickCount();
+ if (m_pStatusChangedCb != NULL)
+ m_pStatusChangedCb(0, m_statusChangedCbData);
+ }
+
+ if (m_action == IA_CONNECT)
+ {
+ m_action = IA_NONE;
+ NetSend(CONN_SYN_N);
+ m_phase = 2;
+ m_phaseTime = GetTickCount();
+ }
+
+ break;
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
-Sleep(20);
-return;
}
//---------------------------------------------------------------------------
void IA_CLIENT_PROT::GetStat(LOADSTAT * ls)
#include <string>
#include <vector>
#include <map>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
-#include <pthread.h>
#else
#include <winsock2.h>
#endif
//---------------------------------------------------------------------------
class IA_CLIENT_PROT
{
-#ifdef WIN32
-friend unsigned long WINAPI RunW(void * data);
-#else
-friend void * RunL(void * data);
-#endif
-
public:
IA_CLIENT_PROT(const std::string & sn, uint16_t p, const std::string & localName = "", uint16_t localPort = 0);
~IA_CLIENT_PROT();
uint32_t GetIP() const { return m_ip; };
private:
- void Run();
+ void Run(std::stop_token token);
int NetRecv();
int NetSend(int n);
- bool GetNonstop() const { return m_nonstop; };
void PrepareNet();
int DeterminatePacketType(const char * buffer);
std::string m_infoText;
mutable std::string m_strError;
mutable int m_codeError;
- bool m_nonstop;
bool m_isNetPrepared;
bool m_proxyMode;
#ifdef WIN32
WSADATA m_wsaData;
#else
- pthread_t m_thread;
+ std::jthread m_thread;
#endif
std::string m_serverName;
std::map<std::string, int> m_packetTypes;
CONN_SYN_8 * m_connSyn8;
- const CONN_SYN_ACK_8 * m_connSynAck8;
+ const CONN_SYN_ACK_8 * m_connSynAck8;
CONN_ACK_8 * m_connAck8;
- const ALIVE_SYN_8 * m_aliveSyn8;
+ const ALIVE_SYN_8 * m_aliveSyn8;
ALIVE_ACK_8 * m_aliveAck8;
DISCONN_SYN_8 * m_disconnSyn8;
const DISCONN_SYN_ACK_8 * m_disconnSynAck8;
DISCONN_ACK_8 * m_disconnAck8;
- const INFO_8 * m_info;
+ const INFO_8 * m_info;
};
//---------------------------------------------------------------------------
-#ifdef WIN32
-unsigned long WINAPI RunW(void *);
-#else
-void * RunW(void *);
-#endif
#pragma once
#include <string>
-#include <list>
#include <map>
+#include <mutex>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
#include <ctime>
#include <cstdint>
class STG_PINGER
{
public:
- typedef std::multimap<uint32_t, time_t> PingIPs;
- typedef PingIPs::size_type SizeType;
+ using PingIPs = std::multimap<uint32_t, time_t>;
- explicit STG_PINGER(time_t delay = 15);
- ~STG_PINGER();
+ explicit STG_PINGER(unsigned delay = 15);
- int Start();
- int Stop();
+ bool Start();
+ bool Stop();
void AddIP(uint32_t ip);
void DelIP(uint32_t ip);
- SizeType GetPingIPNum() const { return m_pingIP.size(); }
+ auto GetPingIPNum() const { std::lock_guard lock(m_mutex); return m_pingIPs.size(); }
void PrintAllIP();
- int GetIPTime(uint32_t ip, time_t * t) const;
- void SetDelayTime(time_t d) { m_delay = d; }
- time_t GetDelayTime() const { return m_delay; }
- const std::string & GetStrError() const { return m_errorStr; }
+ bool GetIPTime(uint32_t ip, time_t& t) const;
+ void SetDelayTime(unsigned d) { m_delay = d; }
+ unsigned GetDelayTime() const { return m_delay; }
+ const std::string& GetStrError() const { return m_errorStr; }
private:
- uint16_t PingCheckSum(void * data, int len);
- int SendPing(uint32_t ip);
+ uint16_t PingCheckSum(const void* data, int len);
+ bool SendPing(uint32_t ip);
uint32_t RecvPing();
- void RealAddIP();
- void RealDelIP();
- static void * RunSendPing(void * d);
- static void * RunRecvPing(void * d);
+ void RunSendPing(std::stop_token token);
+ void RunRecvPing(std::stop_token token);
- time_t m_delay;
- bool m_nonstop;
+ mutable std::mutex m_mutex;
+
+ unsigned m_delay;
bool m_isRunningRecver;
bool m_isRunningSender;
int m_sendSocket;
int m_recvSocket;
- pthread_t m_sendThread;
- pthread_t m_recvThread;
+ std::jthread m_sendThread;
+ std::jthread m_recvThread;
PING_MESSAGE m_pmSend;
uint32_t m_pid;
std::string m_errorStr;
- std::multimap<uint32_t, time_t> m_pingIP;
- std::list<uint32_t> m_ipToAdd;
- std::list<uint32_t> m_ipToDel;
-
- mutable pthread_mutex_t m_mutex;
+ PingIPs m_pingIPs;
};
-#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 <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
//-----------------------------------------------------------------------------
-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<uint32_t>(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<uint32_t>(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<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(&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));
+ 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));
-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<sockaddr*>(&addr), sizeof(addr)) <= 0 )
+ if (sendto(m_sendSocket, &m_pmSend, sizeof(m_pmSend), 0, reinterpret_cast<sockaddr*>(&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<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 != m_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);
-
-auto* pinger = static_cast<STG_PINGER *>(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<uint32_t, time_t>::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<STG_PINGER *>(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;
}
//-----------------------------------------------------------------------------
#define LISTEN_PORT (5580)
#include "css.h"
-
-//---------------------------------------------------------------------------
-#ifndef WIN32
-void * RunWeb(void *)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-#else
-unsigned long WINAPI RunWeb(void *)
-{
-#endif
-while (1)
- web->Run();
-return NULL;
-}
//---------------------------------------------------------------------------
WEB::WEB()
: m_res(0),
//---------------------------------------------------------------------------
void WEB::Start()
{
-#ifdef WIN32
-unsigned long pt;
-CreateThread(
- NULL, // pointer to thread security attributes
- 16384, // initial thread stack size, in bytes
- RunWeb, // pointer to thread function
- NULL, // argument for new thread
- 0, // CREATE_SUSPENDED, // creation flags
- &pt // pointer to returned thread identifier
- );
-#else
-pthread_create(&m_thread, NULL, RunWeb, NULL);
-#endif
+m_thread = std::jthread([this](auto token){ Run(std::move(token)); });
}
//---------------------------------------------------------------------------
void WEB::PrepareNet()
m_listenWebAddr = ip;
}
//---------------------------------------------------------------------------
-void WEB::Run()
+void WEB::Run(std::stop_token token) noexcept
{
+sigset_t signalSet;
+sigfillset(&signalSet);
+pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
+
PrepareNet();
char recvBuffer[4096];
-while (1)
+while (!token.stop_requested())
{
struct sockaddr_in outerAddr;
#include <string>
#include <list>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
#ifndef WIN32
-#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
{
public:
WEB();
- void Run();
void SetDirName(const std::string & dn, int n);
void SetRefreshPagePeriod(int p);
void SetListenAddr(uint32_t ip);
void UpdateStat(const LOADSTAT & ls);
void Start();
private:
+ void Run(std::stop_token token) noexcept;
void PrepareNet();
int SendReply();
int SendCSS();
#ifdef WIN32
WSADATA m_wsaData;
- #else
- pthread_t m_thread;
#endif
+ std::jthread m_thread;
+
std::string m_dirName[DIR_NUM];
int m_res;
int m_listenSocket;
#include <netinet/in.h>
#include <arpa/inet.h>
+using STG::NF_CAP;
+
namespace
{
-struct NF_HEADER {
+struct NF_HEADER
+{
uint16_t version; // Protocol version
uint16_t count; // Flows count
uint32_t uptime; // System uptime
uint16_t sInterval; // Sampling mode and interval
};
-struct NF_DATA {
+struct NF_DATA
+{
uint32_t srcAddr; // Flow source address
uint32_t dstAddr; // Flow destination address
uint32_t nextHop; // IP addres on next hop router
NF_CAP::NF_CAP()
: traffCnt(NULL),
- runningTCP(false),
- runningUDP(false),
stoppedTCP(true),
stoppedUDP(true),
portT(0),
portU(0),
sockTCP(-1),
sockUDP(-1),
- logger(STG::PluginLogger::get("cap_nf"))
+ logger(PluginLogger::get("cap_nf"))
{
}
int NF_CAP::ParseSettings()
{
-std::vector<STG::ParamValue>::iterator it;
+std::vector<ParamValue>::iterator it;
for (it = settings.moduleParams.begin(); it != settings.moduleParams.end(); ++it)
{
if (it->param == "TCPPort" && !it->value.empty())
{
return -1;
}
- runningUDP = true;
- if (pthread_create(&tidUDP, NULL, RunUDP, this))
- {
- runningUDP = false;
- CloseUDP();
- errorStr = "Cannot create UDP thread";
- logger("Cannot create UDP thread.");
- printfd(__FILE__, "Error: Cannot create UDP thread\n");
- return -1;
- }
+ m_threadUDP = std::jthread([this](auto token){ RunUDP(std::move(token)); });
}
if (portT > 0)
{
{
return -1;
}
- runningTCP = true;
- if (pthread_create(&tidTCP, NULL, RunTCP, this))
- {
- runningTCP = false;
- CloseTCP();
- logger("Cannot create TCP thread.");
- errorStr = "Cannot create TCP thread";
- printfd(__FILE__, "Error: Cannot create TCP thread\n");
- return -1;
- }
+ m_threadTCP = std::jthread([this](auto token){ RunTCP(std::move(token)); });
}
return 0;
}
int NF_CAP::Stop()
{
-runningTCP = runningUDP = false;
+m_threadTCP.request_stop();
+m_threadUDP.request_stop();
if (portU && !stoppedUDP)
{
CloseUDP();
}
if (stoppedUDP)
{
- pthread_join(tidUDP, NULL);
+ m_threadUDP.join();
}
else
{
- if (pthread_kill(tidUDP, SIGUSR1))
- {
- errorStr = "Error sending signal to UDP thread";
- logger("Error sending sugnal to UDP thread.");
- printfd(__FILE__, "Error: Error sending signal to UDP thread\n");
- return -1;
- }
+ m_threadUDP.detach();
printfd(__FILE__, "UDP thread NOT stopped\n");
logger("Cannot stop UDP thread.");
}
}
if (stoppedTCP)
{
- pthread_join(tidTCP, NULL);
+ m_threadTCP.join();
}
else
{
- if (pthread_kill(tidTCP, SIGUSR1))
- {
- errorStr = "Error sending signal to TCP thread";
- logger("Error sending signal to TCP thread.");
- printfd(__FILE__, "Error: Error sending signal to TCP thread\n");
- return -1;
- }
+ m_threadTCP.detach();
printfd(__FILE__, "TCP thread NOT stopped\n");
logger("Cannot stop TCP thread.");
}
return false;
}
-void * NF_CAP::RunUDP(void * c)
+void NF_CAP::RunUDP(std::stop_token token) noexcept
{
sigset_t signalSet;
sigfillset(&signalSet);
pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-NF_CAP * cap = static_cast<NF_CAP *>(c);
-cap->stoppedUDP = false;
-while (cap->runningUDP)
+stoppedUDP = false;
+while (!token.stop_requested())
{
- if (!WaitPackets(cap->sockUDP))
+ if (!WaitPackets(sockUDP))
{
continue;
}
struct sockaddr_in sin;
socklen_t slen = sizeof(sin);
uint8_t buf[BUF_SIZE];
- ssize_t res = recvfrom(cap->sockUDP, buf, BUF_SIZE, 0, reinterpret_cast<struct sockaddr *>(&sin), &slen);
- if (!cap->runningUDP)
+ ssize_t res = recvfrom(sockUDP, buf, BUF_SIZE, 0, reinterpret_cast<struct sockaddr *>(&sin), &slen);
+ if (token.stop_requested())
break;
if (res < 0)
{
- cap->logger("recvfrom error: %s", strerror(errno));
+ logger("recvfrom error: %s", strerror(errno));
continue;
}
{
if (errno != EINTR)
{
- cap->errorStr = "Invalid data received";
+ errorStr = "Invalid data received";
printfd(__FILE__, "Error: Invalid data received through UDP\n");
}
continue;
}
- cap->ParseBuffer(buf, res);
+ ParseBuffer(buf, res);
}
-cap->stoppedUDP = true;
-return NULL;
+stoppedUDP = true;
}
-void * NF_CAP::RunTCP(void * c)
+void NF_CAP::RunTCP(std::stop_token token) noexcept
{
sigset_t signalSet;
sigfillset(&signalSet);
pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-NF_CAP * cap = static_cast<NF_CAP *>(c);
-cap->stoppedTCP = false;
-while (cap->runningTCP)
+stoppedTCP = false;
+while (!token.stop_requested())
{
- if (!WaitPackets(cap->sockTCP))
+ if (!WaitPackets(sockTCP))
{
continue;
}
// Data
struct sockaddr_in sin;
socklen_t slen = sizeof(sin);
- int sd = accept(cap->sockTCP, reinterpret_cast<struct sockaddr *>(&sin), &slen);
- if (!cap->runningTCP)
+ int sd = accept(sockTCP, reinterpret_cast<struct sockaddr *>(&sin), &slen);
+ if (token.stop_requested())
break;
if (sd <= 0)
{
if (sd < 0)
- cap->logger("accept error: %s", strerror(errno));
+ logger("accept error: %s", strerror(errno));
continue;
}
ssize_t res = recv(sd, buf, BUF_SIZE, MSG_WAITALL);
if (res < 0)
- cap->logger("recv error: %s", strerror(errno));
+ logger("recv error: %s", strerror(errno));
close(sd);
- if (!cap->runningTCP)
+ if (token.stop_requested())
break;
if (res == 0) // EOF
continue;
}
- cap->ParseBuffer(buf, res);
+ ParseBuffer(buf, res);
}
-cap->stoppedTCP = true;
-return NULL;
+stoppedTCP = true;
}
void NF_CAP::ParseBuffer(uint8_t * buf, ssize_t size)
{
-STG::RawPacket ip;
+RawPacket ip;
NF_HEADER * hdr = reinterpret_cast<NF_HEADER *>(buf);
if (htons(hdr->version) != 5)
{
#include "stg/logger.h"
#include <string>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
#include <cstdint>
-#include <pthread.h>
#include <unistd.h> // close
#define VERSION "cap_nf v. 0.4"
struct Store;
struct Settings;
-}
-
-class NF_CAP : public STG::Plugin {
-public:
- NF_CAP();
-
- void SetTraffcounter(STG::TraffCounter * tc) override { traffCnt = tc; }
- void SetSettings(const STG::ModuleSettings & s) override { settings = s; }
- int ParseSettings() override;
-
- int Start() override;
- int Stop() override;
- int Reload(const STG::ModuleSettings & /*ms*/) override { return 0; }
-
- bool IsRunning() override { return runningTCP || runningUDP; }
- const std::string & GetStrError() const override { return errorStr; }
- std::string GetVersion() const override { return VERSION; }
- uint16_t GetStartPosition() const override { return START_POS; }
- uint16_t GetStopPosition() const override { return STOP_POS; }
-
-private:
- NF_CAP(const NF_CAP & rvalue);
- NF_CAP & operator=(const NF_CAP & rvalue);
-
- STG::TraffCounter * traffCnt;
- STG::ModuleSettings settings;
- pthread_t tidTCP;
- pthread_t tidUDP;
- bool runningTCP;
- bool runningUDP;
- bool stoppedTCP;
- bool stoppedUDP;
- uint16_t portT;
- uint16_t portU;
- int sockTCP;
- int sockUDP;
- mutable std::string errorStr;
- STG::PluginLogger logger;
-
- static void * RunUDP(void *);
- static void * RunTCP(void *);
- void ParseBuffer(uint8_t * buf, ssize_t size);
-
- bool OpenTCP();
- bool OpenUDP();
- void CloseTCP() { close(sockTCP); }
- void CloseUDP() { close(sockUDP); }
+class NF_CAP : public Plugin
+{
+ public:
+ NF_CAP();
+
+ void SetTraffcounter(TraffCounter * tc) override { traffCnt = tc; }
+ void SetSettings(const ModuleSettings & s) override { settings = s; }
+ int ParseSettings() override;
+
+ int Start() override;
+ int Stop() override;
+ int Reload(const ModuleSettings & /*ms*/) override { return 0; }
+
+ bool IsRunning() override { return m_threadTCP.joinable() || m_threadUDP.joinable(); }
+ const std::string & GetStrError() const override { return errorStr; }
+ std::string GetVersion() const override { return VERSION; }
+ uint16_t GetStartPosition() const override { return START_POS; }
+ uint16_t GetStopPosition() const override { return STOP_POS; }
+
+ private:
+ NF_CAP(const NF_CAP & rvalue);
+ NF_CAP & operator=(const NF_CAP & rvalue);
+
+ TraffCounter * traffCnt;
+ ModuleSettings settings;
+ std::jthread m_threadTCP;
+ std::jthread m_threadUDP;
+ bool stoppedTCP;
+ bool stoppedUDP;
+ uint16_t portT;
+ uint16_t portU;
+ int sockTCP;
+ int sockUDP;
+ mutable std::string errorStr;
+ PluginLogger logger;
+
+ void RunUDP(std::stop_token token) noexcept;
+ void RunTCP(std::stop_token token) noexcept;
+ void ParseBuffer(uint8_t * buf, ssize_t size);
+
+ bool OpenTCP();
+ bool OpenUDP();
+ void CloseTCP() { close(sockTCP); }
+ void CloseUDP() { close(sockUDP); }
};
+
+}
DIVERT_CAP::DIVERT_CAP()
: port(0),
disableForwarding(false),
- nonstop(false),
isRunning(false),
traffCnt(NULL),
logger(STG::PluginLogger::get("cap_divert"))
return -1;
}
-nonstop = true;
-
-if (pthread_create(&thread, NULL, Run, this))
- {
- errorStr = "Cannot create thread.";
- logger("Cannot create thread.");
- printfd(__FILE__, "Cannot create thread\n");
- return -1;
- }
+m_thread = std::jthread([](auto token){ Run(std::move(token)); });
return 0;
}
DivertCapClose();
-nonstop = false;
-
+m_thread.request_stop();
//5 seconds to thread stops itself
-int i;
-for (i = 0; i < 25; i++)
+for (size_t i = 0; i < 25; i++)
{
if (!isRunning)
break;
//after 5 seconds waiting thread still running. now killing it
if (isRunning)
- {
- if (pthread_kill(thread, SIGINT))
- {
- errorStr = "Cannot kill thread.";
- logger("Cannot send signal to thread.");
- printfd(__FILE__, "Cannot kill thread\n");
- return -1;
- }
- }
+ m_thread.detach();
+else
+ m_thread.join();
return 0;
}
//-----------------------------------------------------------------------------
-void * DIVERT_CAP::Run(void * d)
+void DIVERT_CAP::Run(std::stop_token token) noexcept
{
sigset_t signalSet;
sigfillset(&signalSet);
pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-DIVERT_CAP * dc = static_cast<DIVERT_CAP *>(d);
-dc->isRunning = true;
+isRunning = true;
char buffer[STG::packetSize + 14];
-while (dc->nonstop)
+while (!token.stop_requested())
{
STG::RawPacket rp;
- dc->DivertCapRead(buffer, sizeof(buffer), NULL);
+ DivertCapRead(buffer, sizeof(buffer), NULL);
if (buffer[12] != 0x8)
continue;
memcpy(&rp.rawPacket, &buffer[14], STG::packetSize);
- dc->traffCnt->process(rp);
+ traffCnt->process(rp);
}
-dc->isRunning = false;
-return NULL;
+isRunning = false;
}
//-----------------------------------------------------------------------------
int DIVERT_CAP::DivertCapOpen()
#include "stg/logger.h"
#include <string>
-
-#include <pthread.h>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
namespace STG
{
DIVERT_CAP(const DIVERT_CAP & rvalue);
DIVERT_CAP & operator=(const DIVERT_CAP & rvalue);
- static void * Run(void *);
+ void Run(std::stop_token token) noexcept;
int DivertCapOpen();
int DivertCapOpen(int n);
mutable std::string errorStr;
- pthread_t thread;
+ std::jthread m_thread;
- bool nonstop;
bool isRunning;
STG::TraffCounter * traffCnt;
m_onAddUserConn = users->onAdd([this](auto user){ AddUser(user); });
m_onDelUserConn = users->onDel([this](auto user){ DelUser(user); });
-pinger.SetDelayTime(pingSettings.GetPingDelay());
-pinger.Start();
+m_pinger.SetDelayTime(pingSettings.GetPingDelay());
+m_pinger.Start();
m_thread = std::jthread([this](auto token){ Run(std::move(token)); });
if (!m_thread.joinable())
return 0;
-pinger.Stop();
+m_pinger.Stop();
m_thread.request_stop();
//5 seconds to thread stops itself
struct timespec ts = {0, 200000000};
{
uint32_t ip = (*iter)->GetProperties().ips.ConstData()[0].ip;
time_t t;
- if (pinger.GetIPTime(ip, &t) == 0)
+ if (m_pinger.GetIPTime(ip, t) == 0)
{
if (t != 0)
(*iter)->UpdatePingTime(t);
if (ip != 0)
{
time_t t;
- if (pinger.GetIPTime(ip, &t) == 0)
+ if (m_pinger.GetIPTime(ip, t) == 0)
{
if (t != 0)
(*iter)->UpdatePingTime(t);
SetUserNotifiers(u);
if (u->GetProperties().ips.ConstData().onlyOneIP())
{
- pinger.AddIP(u->GetProperties().ips.ConstData()[0].ip);
+ m_pinger.AddIP(u->GetProperties().ips.ConstData()[0].ip);
}
else
{
uint32_t ip = u->GetCurrIP();
if (ip != 0)
- pinger.AddIP(ip);
+ m_pinger.AddIP(ip);
}
}
//-----------------------------------------------------------------------------
void PING::updateCurrIP(uint32_t oldVal, uint32_t newVal)
{
- pinger.DelIP(oldVal);
+ m_pinger.DelIP(oldVal);
if (newVal != 0)
- pinger.AddIP(newVal);
+ m_pinger.AddIP(newVal);
}
//-----------------------------------------------------------------------------
void PING::updateIPs(const UserIPs& oldVal, const UserIPs& newVal)
{
if (oldVal.onlyOneIP())
- pinger.DelIP(oldVal[0].ip);
+ m_pinger.DelIP(oldVal[0].ip);
if (newVal.onlyOneIP())
- pinger.AddIP(newVal[0].ip);
+ m_pinger.AddIP(newVal[0].ip);
}
void UnSetUserNotifiers(UserPtr u);
void Run(std::stop_token token);
- mutable std::string errorStr;
+ std::string errorStr;
PING_SETTINGS pingSettings;
ModuleSettings settings;
Users * users;
std::jthread m_thread;
std::mutex m_mutex;
bool isRunning;
- mutable STG_PINGER pinger;
+ STG_PINGER m_pinger;
void updateCurrIP(uint32_t oldVal, uint32_t newVal);
void updateIPs(const UserIPs& oldVal, const UserIPs& newVal);
m_onIPConns.clear();
//5 seconds to thread stops itself
-struct timespec ts = {0, 200000000};
for (int i = 0; i < 25 && !stopped; i++)
- nanosleep(&ts, NULL);
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
if (!stopped)
{
int c = 0;
time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
-struct timespec ts = {0, 500000000};
while (!token.stop_requested())
{
- nanosleep(&ts, 0);
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
if (token.stop_requested())
{
FlushAndRemove();