6 #include <sys/socket.h>
7 #include <netinet/in.h>
18 #include "stg/common.h"
19 #include "stg/locker.h"
22 extern volatile time_t stgTime;
25 //-----------------------------------------------------------------------------
26 STG_PINGER::STG_PINGER(time_t d)
29 isRunningRecver(false),
30 isRunningSender(false),
43 pthread_mutex_init(&mutex, NULL);
44 memset(&pmSend, 0, sizeof(pmSend));
46 //-----------------------------------------------------------------------------
47 STG_PINGER::~STG_PINGER()
49 pthread_mutex_destroy(&mutex);
51 //-----------------------------------------------------------------------------
52 int STG_PINGER::Start()
54 struct protoent *proto = NULL;
55 proto = getprotobyname("ICMP");
56 sendSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
57 recvSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
59 pid = (int) getpid() % 65535;
60 if (sendSocket < 0 || recvSocket < 0)
62 errorStr = "Cannot create socket.";
66 if (pthread_create(&sendThread, NULL, RunSendPing, this))
68 errorStr = "Cannot create send thread.";
72 if (pthread_create(&recvThread, NULL, RunRecvPing, this))
74 errorStr = "Cannot create recv thread.";
80 //-----------------------------------------------------------------------------
81 int STG_PINGER::Stop()
87 //5 seconds to thread stops itself
88 for (size_t i = 0; i < 25; i++)
91 SendPing(0x0100007f);//127.0.0.1
96 struct timespec ts = {0, 200000000};
100 //after 5 seconds waiting thread still running. now killing it
103 if (pthread_kill(recvThread, SIGINT))
105 errorStr = "Cannot kill thread.";
113 //5 seconds to thread stops itself
114 for (size_t i = 0; i < 25; i++)
116 if (!isRunningSender)
119 struct timespec ts = {0, 200000000};
120 nanosleep(&ts, NULL);
123 //after 5 seconds waiting thread still running. now killing it
126 if (pthread_kill(sendThread, SIGINT))
128 errorStr = "Cannot kill thread.";
137 //-----------------------------------------------------------------------------
138 void STG_PINGER::AddIP(uint32_t ip)
140 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
141 ipToAdd.push_back(ip);
143 //-----------------------------------------------------------------------------
144 void STG_PINGER::DelIP(uint32_t ip)
146 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
147 ipToDel.push_back(ip);
149 //-----------------------------------------------------------------------------
150 void STG_PINGER::RealAddIP()
152 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
154 std::list<uint32_t>::iterator iter;
155 iter = ipToAdd.begin();
156 while (iter != ipToAdd.end())
158 pingIP.insert(std::make_pair(*iter, 0));
161 ipToAdd.erase(ipToAdd.begin(), ipToAdd.end());
163 //-----------------------------------------------------------------------------
164 void STG_PINGER::RealDelIP()
166 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
168 std::list<uint32_t>::iterator iter;
169 std::multimap<uint32_t, time_t>::iterator treeIter;
170 iter = ipToDel.begin();
171 while (iter != ipToDel.end())
173 treeIter = pingIP.find(*iter);
174 if (treeIter != pingIP.end())
175 pingIP.erase(treeIter);
179 ipToDel.erase(ipToDel.begin(), ipToDel.end());
181 //-----------------------------------------------------------------------------
182 int STG_PINGER::GetPingIPNum() const
184 return pingIP.size();
186 //-----------------------------------------------------------------------------
187 void STG_PINGER::PrintAllIP()
189 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
190 std::multimap<uint32_t, time_t>::iterator iter;
191 iter = pingIP.begin();
192 while (iter != pingIP.end())
194 uint32_t ip = iter->first;
195 time_t t = iter->second;
198 printf("ip = %s, time = %9s\n", inet_ntostring(ip).c_str(), s.c_str());
203 //-----------------------------------------------------------------------------
204 int STG_PINGER::GetIPTime(uint32_t ip, time_t * t) const
206 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
207 std::multimap<uint32_t, time_t>::const_iterator treeIter;
209 treeIter = pingIP.find(ip);
210 if (treeIter == pingIP.end())
213 *t = treeIter->second;
216 //-----------------------------------------------------------------------------
217 uint16_t STG_PINGER::PingCheckSum(void * data, int len)
219 unsigned short * buf = (unsigned short *)data;
220 unsigned int sum = 0;
221 unsigned short result;
223 for ( sum = 0; len > 1; len -= 2 )
227 sum += *(unsigned char*)buf;
229 sum = (sum >> 16) + (sum & 0xFFFF);
234 //-----------------------------------------------------------------------------
235 int STG_PINGER::SendPing(uint32_t ip)
237 struct sockaddr_in addr;
238 memset(&addr, 0, sizeof(addr));
239 addr.sin_family = AF_INET;
241 addr.sin_addr.s_addr = ip;
243 memset(&pmSend, 0, sizeof(pmSend));
244 pmSend.hdr.type = ICMP_ECHO;
245 pmSend.hdr.un.echo.id = pid;
246 memcpy(pmSend.msg, &ip, sizeof(ip));
248 pmSend.hdr.checksum = PingCheckSum(&pmSend, sizeof(pmSend));
250 if (sendto(sendSocket, &pmSend, sizeof(pmSend), 0, (sockaddr *)&addr, sizeof(addr)) <= 0 )
252 errorStr = "Send ping error: " + std::string(strerror(errno));
259 //-----------------------------------------------------------------------------
260 uint32_t STG_PINGER::RecvPing()
262 struct sockaddr_in addr;
266 memset(buf, 0, sizeof(buf));
268 socklen_t len = sizeof(addr);
270 bytes = recvfrom(recvSocket, &buf, sizeof(buf), 0, (struct sockaddr*)&addr, &len);
273 struct IP_HDR * ip = (struct IP_HDR *)buf;
274 struct ICMP_HDR *icmp = (struct ICMP_HDR *)(buf + ip->ihl * 4);
276 if (icmp->un.echo.id != pid)
279 ipAddr = *(uint32_t*)(buf + sizeof(ICMP_HDR) + ip->ihl * 4);
284 //-----------------------------------------------------------------------------
285 void * STG_PINGER::RunSendPing(void * d)
287 STG_PINGER * pinger = static_cast<STG_PINGER *>(d);
289 pinger->isRunningSender = true;
291 while (pinger->nonstop)
296 std::multimap<uint32_t, time_t>::iterator iter;
297 iter = pinger->pingIP.begin();
298 while (iter != pinger->pingIP.end())
300 pinger->SendPing(iter->first);
310 currTime = lastPing = time(NULL);
313 while (currTime - lastPing < pinger->delay && pinger->nonstop)
318 currTime = time(NULL);
320 struct timespec ts = {0, 20000000};
321 nanosleep(&ts, NULL);
325 pinger->isRunningSender = false;
329 //-----------------------------------------------------------------------------
330 void * STG_PINGER::RunRecvPing(void * d)
332 STG_PINGER * pinger = static_cast<STG_PINGER *>(d);
334 pinger->isRunningRecver = true;
336 while (pinger->nonstop)
338 uint32_t ip = pinger->RecvPing();
342 std::multimap<uint32_t, time_t>::iterator treeIterUpper = pinger->pingIP.upper_bound(ip);
343 std::multimap<uint32_t, time_t>::iterator treeIterLower = pinger->pingIP.lower_bound(ip);
344 while (treeIterUpper != treeIterLower)
347 treeIterLower->second = stgTime;
349 treeIterLower->second = time(NULL);
356 pinger->isRunningRecver = false;
359 //-----------------------------------------------------------------------------