4 #include <sys/socket.h>
 
   5 #include <netinet/in.h>
 
  18 #include "stg/common.h"
 
  19 #include "stg/locker.h"
 
  21 #include "stg/pinger.h"
 
  24 extern volatile time_t stgTime;
 
  27 //-----------------------------------------------------------------------------
 
  28 STG_PINGER::STG_PINGER(time_t d)
 
  31       isRunningRecver(false),
 
  32       isRunningSender(false),
 
  45 pthread_mutex_init(&mutex, NULL);
 
  46 memset(&pmSend, 0, sizeof(pmSend));
 
  48 //-----------------------------------------------------------------------------
 
  49 STG_PINGER::~STG_PINGER()
 
  51 pthread_mutex_destroy(&mutex);
 
  53 //-----------------------------------------------------------------------------
 
  54 int STG_PINGER::Start()
 
  56 struct protoent *proto = NULL;
 
  57 proto = getprotobyname("ICMP");
 
  58 sendSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
 
  59 recvSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
 
  61 pid = (int) getpid() % 65535;
 
  62 if (sendSocket < 0 || recvSocket < 0)
 
  64     errorStr = "Cannot create socket.";
 
  68 if (pthread_create(&sendThread, NULL, RunSendPing, this))
 
  70     errorStr = "Cannot create send thread.";
 
  74 if (pthread_create(&recvThread, NULL, RunRecvPing, this))
 
  76     errorStr = "Cannot create recv thread.";
 
  82 //-----------------------------------------------------------------------------
 
  83 int STG_PINGER::Stop()
 
  89     //5 seconds to thread stops itself
 
  90     for (size_t i = 0; i < 25; i++)
 
  93             SendPing(0x0100007f);//127.0.0.1
 
  98         struct timespec ts = {0, 200000000};
 
 105     //5 seconds to thread stops itself
 
 106     for (size_t i = 0; i < 25; i++)
 
 108         if (!isRunningSender)
 
 111         struct timespec ts = {0, 200000000};
 
 112         nanosleep(&ts, NULL);
 
 118 if (isRunningSender || isRunningRecver)
 
 123 //-----------------------------------------------------------------------------
 
 124 void STG_PINGER::AddIP(uint32_t ip)
 
 126 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 127 ipToAdd.push_back(ip);
 
 129 //-----------------------------------------------------------------------------
 
 130 void STG_PINGER::DelIP(uint32_t ip)
 
 132 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 133 ipToDel.push_back(ip);
 
 135 //-----------------------------------------------------------------------------
 
 136 void STG_PINGER::RealAddIP()
 
 138 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 140 std::list<uint32_t>::iterator iter;
 
 141 iter = ipToAdd.begin();
 
 142 while (iter != ipToAdd.end())
 
 144     pingIP.insert(std::make_pair(*iter, 0));
 
 147 ipToAdd.erase(ipToAdd.begin(), ipToAdd.end());
 
 149 //-----------------------------------------------------------------------------
 
 150 void STG_PINGER::RealDelIP()
 
 152 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 154 std::list<uint32_t>::iterator iter;
 
 155 std::multimap<uint32_t, time_t>::iterator treeIter;
 
 156 iter = ipToDel.begin();
 
 157 while (iter != ipToDel.end())
 
 159     treeIter = pingIP.find(*iter);
 
 160     if (treeIter != pingIP.end())
 
 161         pingIP.erase(treeIter);
 
 165 ipToDel.erase(ipToDel.begin(), ipToDel.end());
 
 167 //-----------------------------------------------------------------------------
 
 168 void STG_PINGER::PrintAllIP()
 
 170 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 171 std::multimap<uint32_t, time_t>::iterator iter;
 
 172 iter = pingIP.begin();
 
 173 while (iter != pingIP.end())
 
 175     uint32_t ip = iter->first;
 
 176     time_t t = iter->second;
 
 179     printf("ip = %s, time = %9s\n", inet_ntostring(ip).c_str(), s.c_str());
 
 184 //-----------------------------------------------------------------------------
 
 185 int STG_PINGER::GetIPTime(uint32_t ip, time_t * t) const
 
 187 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
 
 188 std::multimap<uint32_t, time_t>::const_iterator treeIter;
 
 190 treeIter = pingIP.find(ip);
 
 191 if (treeIter == pingIP.end())
 
 194 *t = treeIter->second;
 
 197 //-----------------------------------------------------------------------------
 
 198 uint16_t STG_PINGER::PingCheckSum(void * data, int len)
 
 200 uint16_t * buf = static_cast<uint16_t *>(data);
 
 204 for ( sum = 0; len > 1; len -= 2 )
 
 208     sum += *reinterpret_cast<uint8_t*>(buf);
 
 210 sum = (sum >> 16) + (sum & 0xFFFF);
 
 213 return static_cast<uint16_t>(result);
 
 215 //-----------------------------------------------------------------------------
 
 216 int STG_PINGER::SendPing(uint32_t ip)
 
 218 struct sockaddr_in addr;
 
 219 memset(&addr, 0, sizeof(addr));
 
 220 addr.sin_family = AF_INET;
 
 222 addr.sin_addr.s_addr = ip;
 
 224 memset(&pmSend, 0, sizeof(pmSend));
 
 225 pmSend.hdr.type = ICMP_ECHO;
 
 226 pmSend.hdr.un.echo.id = static_cast<uint16_t>(pid);
 
 227 memcpy(pmSend.msg, &ip, sizeof(ip));
 
 229 pmSend.hdr.checksum = PingCheckSum(&pmSend, sizeof(pmSend));
 
 231 if (sendto(sendSocket, &pmSend, sizeof(pmSend), 0, (sockaddr *)&addr, sizeof(addr)) <= 0 )
 
 233     errorStr = "Send ping error: " + std::string(strerror(errno));
 
 240 //-----------------------------------------------------------------------------
 
 241 uint32_t STG_PINGER::RecvPing()
 
 243 struct sockaddr_in addr;
 
 247 memset(buf, 0, sizeof(buf));
 
 248 socklen_t len = sizeof(addr);
 
 250 if (recvfrom(recvSocket, &buf, sizeof(buf), 0, reinterpret_cast<struct sockaddr*>(&addr), &len))
 
 252     struct IP_HDR * ip = static_cast<struct IP_HDR *>(static_cast<void *>(buf));
 
 253     struct ICMP_HDR *icmp = static_cast<struct ICMP_HDR *>(static_cast<void *>(buf + ip->ihl * 4));
 
 255     if (icmp->un.echo.id != pid)
 
 258     ipAddr = *static_cast<uint32_t*>(static_cast<void *>(buf + sizeof(ICMP_HDR) + ip->ihl * 4));
 
 263 //-----------------------------------------------------------------------------
 
 264 void * STG_PINGER::RunSendPing(void * d)
 
 267 sigfillset(&signalSet);
 
 268 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
 
 270 STG_PINGER * pinger = static_cast<STG_PINGER *>(d);
 
 272 pinger->isRunningSender = true;
 
 274 while (pinger->nonstop)
 
 279     std::multimap<uint32_t, time_t>::iterator iter;
 
 280     iter = pinger->pingIP.begin();
 
 281     while (iter != pinger->pingIP.end())
 
 283         pinger->SendPing(iter->first);
 
 293     currTime = lastPing = time(NULL);
 
 296     while (currTime - lastPing < pinger->delay && pinger->nonstop)
 
 301         currTime = time(NULL);
 
 303         struct timespec ts = {0, 20000000};
 
 304         nanosleep(&ts, NULL);
 
 308 pinger->isRunningSender = false;
 
 312 //-----------------------------------------------------------------------------
 
 313 void * STG_PINGER::RunRecvPing(void * d)
 
 316 sigfillset(&signalSet);
 
 317 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
 
 319 STG_PINGER * pinger = static_cast<STG_PINGER *>(d);
 
 321 pinger->isRunningRecver = true;
 
 323 while (pinger->nonstop)
 
 325     uint32_t ip = pinger->RecvPing();
 
 329         std::multimap<uint32_t, time_t>::iterator treeIterUpper = pinger->pingIP.upper_bound(ip);
 
 330         std::multimap<uint32_t, time_t>::iterator treeIterLower = pinger->pingIP.lower_bound(ip);
 
 331         while (treeIterUpper != treeIterLower)
 
 334             treeIterLower->second = stgTime;
 
 336             treeIterLower->second = time(NULL);
 
 343 pinger->isRunningRecver = false;
 
 346 //-----------------------------------------------------------------------------