4 #include <sys/socket.h>
5 #include <netinet/in.h>
18 #include "stg/common.h"
19 #include "stg/locker.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};
102 //after 5 seconds waiting thread still running. now killing it
105 if (pthread_kill(recvThread, SIGINT))
107 errorStr = "Cannot kill thread.";
115 //5 seconds to thread stops itself
116 for (size_t i = 0; i < 25; i++)
118 if (!isRunningSender)
121 struct timespec ts = {0, 200000000};
122 nanosleep(&ts, NULL);
125 //after 5 seconds waiting thread still running. now killing it
128 if (pthread_kill(sendThread, SIGINT))
130 errorStr = "Cannot kill thread.";
139 //-----------------------------------------------------------------------------
140 void STG_PINGER::AddIP(uint32_t ip)
142 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
143 ipToAdd.push_back(ip);
145 //-----------------------------------------------------------------------------
146 void STG_PINGER::DelIP(uint32_t ip)
148 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
149 ipToDel.push_back(ip);
151 //-----------------------------------------------------------------------------
152 void STG_PINGER::RealAddIP()
154 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
156 std::list<uint32_t>::iterator iter;
157 iter = ipToAdd.begin();
158 while (iter != ipToAdd.end())
160 pingIP.insert(std::make_pair(*iter, 0));
163 ipToAdd.erase(ipToAdd.begin(), ipToAdd.end());
165 //-----------------------------------------------------------------------------
166 void STG_PINGER::RealDelIP()
168 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
170 std::list<uint32_t>::iterator iter;
171 std::multimap<uint32_t, time_t>::iterator treeIter;
172 iter = ipToDel.begin();
173 while (iter != ipToDel.end())
175 treeIter = pingIP.find(*iter);
176 if (treeIter != pingIP.end())
177 pingIP.erase(treeIter);
181 ipToDel.erase(ipToDel.begin(), ipToDel.end());
183 //-----------------------------------------------------------------------------
184 int STG_PINGER::GetPingIPNum() const
186 return pingIP.size();
188 //-----------------------------------------------------------------------------
189 void STG_PINGER::PrintAllIP()
191 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
192 std::multimap<uint32_t, time_t>::iterator iter;
193 iter = pingIP.begin();
194 while (iter != pingIP.end())
196 uint32_t ip = iter->first;
197 time_t t = iter->second;
200 printf("ip = %s, time = %9s\n", inet_ntostring(ip).c_str(), s.c_str());
205 //-----------------------------------------------------------------------------
206 int STG_PINGER::GetIPTime(uint32_t ip, time_t * t) const
208 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
209 std::multimap<uint32_t, time_t>::const_iterator treeIter;
211 treeIter = pingIP.find(ip);
212 if (treeIter == pingIP.end())
215 *t = treeIter->second;
218 //-----------------------------------------------------------------------------
219 uint16_t STG_PINGER::PingCheckSum(void * data, int len)
221 unsigned short * buf = (unsigned short *)data;
222 unsigned int sum = 0;
223 unsigned short result;
225 for ( sum = 0; len > 1; len -= 2 )
229 sum += *(unsigned char*)buf;
231 sum = (sum >> 16) + (sum & 0xFFFF);
236 //-----------------------------------------------------------------------------
237 int STG_PINGER::SendPing(uint32_t ip)
239 struct sockaddr_in addr;
240 memset(&addr, 0, sizeof(addr));
241 addr.sin_family = AF_INET;
243 addr.sin_addr.s_addr = ip;
245 memset(&pmSend, 0, sizeof(pmSend));
246 pmSend.hdr.type = ICMP_ECHO;
247 pmSend.hdr.un.echo.id = pid;
248 memcpy(pmSend.msg, &ip, sizeof(ip));
250 pmSend.hdr.checksum = PingCheckSum(&pmSend, sizeof(pmSend));
252 if (sendto(sendSocket, &pmSend, sizeof(pmSend), 0, (sockaddr *)&addr, sizeof(addr)) <= 0 )
254 errorStr = "Send ping error: " + std::string(strerror(errno));
261 //-----------------------------------------------------------------------------
262 uint32_t STG_PINGER::RecvPing()
264 struct sockaddr_in addr;
268 memset(buf, 0, sizeof(buf));
270 socklen_t len = sizeof(addr);
272 bytes = recvfrom(recvSocket, &buf, sizeof(buf), 0, (struct sockaddr*)&addr, &len);
275 struct IP_HDR * ip = (struct IP_HDR *)buf;
276 struct ICMP_HDR *icmp = (struct ICMP_HDR *)(buf + ip->ihl * 4);
278 if (icmp->un.echo.id != pid)
281 ipAddr = *(uint32_t*)(buf + sizeof(ICMP_HDR) + ip->ihl * 4);
286 //-----------------------------------------------------------------------------
287 void * STG_PINGER::RunSendPing(void * d)
290 sigfillset(&signalSet);
291 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
293 STG_PINGER * pinger = static_cast<STG_PINGER *>(d);
295 pinger->isRunningSender = true;
297 while (pinger->nonstop)
302 std::multimap<uint32_t, time_t>::iterator iter;
303 iter = pinger->pingIP.begin();
304 while (iter != pinger->pingIP.end())
306 pinger->SendPing(iter->first);
316 currTime = lastPing = time(NULL);
319 while (currTime - lastPing < pinger->delay && pinger->nonstop)
324 currTime = time(NULL);
326 struct timespec ts = {0, 20000000};
327 nanosleep(&ts, NULL);
331 pinger->isRunningSender = false;
335 //-----------------------------------------------------------------------------
336 void * STG_PINGER::RunRecvPing(void * d)
339 sigfillset(&signalSet);
340 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
342 STG_PINGER * pinger = static_cast<STG_PINGER *>(d);
344 pinger->isRunningRecver = true;
346 while (pinger->nonstop)
348 uint32_t ip = pinger->RecvPing();
352 std::multimap<uint32_t, time_t>::iterator treeIterUpper = pinger->pingIP.upper_bound(ip);
353 std::multimap<uint32_t, time_t>::iterator treeIterLower = pinger->pingIP.lower_bound(ip);
354 while (treeIterUpper != treeIterLower)
357 treeIterLower->second = stgTime;
359 treeIterLower->second = time(NULL);
366 pinger->isRunningRecver = false;
369 //-----------------------------------------------------------------------------