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),
35 pthread_mutex_init(&mutex, NULL);
36 memset(&pmSend, 0, sizeof(pmSend));
38 //-----------------------------------------------------------------------------
39 STG_PINGER::~STG_PINGER()
41 pthread_mutex_destroy(&mutex);
43 //-----------------------------------------------------------------------------
44 int STG_PINGER::Start()
46 struct protoent *proto = NULL;
47 proto = getprotobyname("ICMP");
48 sendSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
49 recvSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
51 pid = (int) getpid() % 65535;
52 if (sendSocket < 0 || recvSocket < 0)
54 errorStr = "Cannot create socket.";
58 if (pthread_create(&sendThread, NULL, RunSendPing, this))
60 errorStr = "Cannot create send thread.";
64 if (pthread_create(&recvThread, NULL, RunRecvPing, this))
66 errorStr = "Cannot create recv thread.";
72 //-----------------------------------------------------------------------------
73 int STG_PINGER::Stop()
79 //5 seconds to thread stops itself
80 for (size_t i = 0; i < 25; i++)
83 SendPing(0x0100007f);//127.0.0.1
91 //after 5 seconds waiting thread still running. now killing it
94 if (pthread_kill(recvThread, SIGINT))
96 errorStr = "Cannot kill thread.";
104 //5 seconds to thread stops itself
105 for (size_t i = 0; i < 25; i++)
107 if (!isRunningSender)
113 //after 5 seconds waiting thread still running. now killing it
116 if (pthread_kill(sendThread, SIGINT))
118 errorStr = "Cannot kill thread.";
127 //-----------------------------------------------------------------------------
128 void STG_PINGER::AddIP(uint32_t ip)
130 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
131 ipToAdd.push_back(ip);
133 //-----------------------------------------------------------------------------
134 void STG_PINGER::DelIP(uint32_t ip)
136 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
137 ipToDel.push_back(ip);
139 //-----------------------------------------------------------------------------
140 void STG_PINGER::RealAddIP()
142 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
144 std::list<uint32_t>::iterator iter;
145 iter = ipToAdd.begin();
146 while (iter != ipToAdd.end())
148 pingIP.insert(std::make_pair(*iter, 0));
151 ipToAdd.erase(ipToAdd.begin(), ipToAdd.end());
153 //-----------------------------------------------------------------------------
154 void STG_PINGER::RealDelIP()
156 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
158 std::list<uint32_t>::iterator iter;
159 std::multimap<uint32_t, time_t>::iterator treeIter;
160 iter = ipToDel.begin();
161 while (iter != ipToDel.end())
163 treeIter = pingIP.find(*iter);
164 if (treeIter != pingIP.end())
165 pingIP.erase(treeIter);
169 ipToDel.erase(ipToDel.begin(), ipToDel.end());
171 //-----------------------------------------------------------------------------
172 int STG_PINGER::GetPingIPNum() const
174 return pingIP.size();
176 //-----------------------------------------------------------------------------
177 void STG_PINGER::PrintAllIP()
179 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
180 std::multimap<uint32_t, time_t>::iterator iter;
181 iter = pingIP.begin();
182 while (iter != pingIP.end())
184 uint32_t ip = iter->first;
185 time_t t = iter->second;
188 printf("ip = %s, time = %9s\n", inet_ntostring(ip).c_str(), s.c_str());
193 //-----------------------------------------------------------------------------
194 int STG_PINGER::GetIPTime(uint32_t ip, time_t * t) const
196 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
197 std::multimap<uint32_t, time_t>::const_iterator treeIter;
199 treeIter = pingIP.find(ip);
200 if (treeIter == pingIP.end())
203 *t = treeIter->second;
206 //-----------------------------------------------------------------------------
207 uint16_t STG_PINGER::PingCheckSum(void * data, int len)
209 unsigned short * buf = (unsigned short *)data;
210 unsigned int sum = 0;
211 unsigned short result;
213 for ( sum = 0; len > 1; len -= 2 )
217 sum += *(unsigned char*)buf;
219 sum = (sum >> 16) + (sum & 0xFFFF);
224 //-----------------------------------------------------------------------------
225 int STG_PINGER::SendPing(uint32_t ip)
227 struct sockaddr_in addr;
228 memset(&addr, 0, sizeof(addr));
229 addr.sin_family = AF_INET;
231 addr.sin_addr.s_addr = ip;
233 memset(&pmSend, 0, sizeof(pmSend));
234 pmSend.hdr.type = ICMP_ECHO;
235 pmSend.hdr.un.echo.id = pid;
236 memcpy(pmSend.msg, &ip, sizeof(ip));
238 pmSend.hdr.checksum = PingCheckSum(&pmSend, sizeof(pmSend));
240 if (sendto(sendSocket, &pmSend, sizeof(pmSend), 0, (sockaddr *)&addr, sizeof(addr)) <= 0 )
242 errorStr = "Send ping error: " + std::string(strerror(errno));
249 //-----------------------------------------------------------------------------
250 uint32_t STG_PINGER::RecvPing()
252 struct sockaddr_in addr;
256 memset(buf, 0, sizeof(buf));
258 socklen_t len = sizeof(addr);
260 bytes = recvfrom(recvSocket, &buf, sizeof(buf), 0, (struct sockaddr*)&addr, &len);
263 struct IP_HDR * ip = (struct IP_HDR *)buf;
264 struct ICMP_HDR *icmp = (struct ICMP_HDR *)(buf + ip->ihl * 4);
266 if (icmp->un.echo.id != pid)
269 ipAddr = *(uint32_t*)(buf + sizeof(ICMP_HDR) + ip->ihl * 4);
274 //-----------------------------------------------------------------------------
275 void * STG_PINGER::RunSendPing(void * d)
277 STG_PINGER * pinger = static_cast<STG_PINGER *>(d);
279 pinger->isRunningSender = true;
281 while (pinger->nonstop)
286 std::multimap<uint32_t, time_t>::iterator iter;
287 iter = pinger->pingIP.begin();
288 while (iter != pinger->pingIP.end())
290 pinger->SendPing(iter->first);
300 currTime = lastPing = time(NULL);
303 while (currTime - lastPing < pinger->delay && pinger->nonstop)
308 currTime = time(NULL);
314 pinger->isRunningSender = false;
318 //-----------------------------------------------------------------------------
319 void * STG_PINGER::RunRecvPing(void * d)
321 STG_PINGER * pinger = static_cast<STG_PINGER *>(d);
323 pinger->isRunningRecver = true;
325 while (pinger->nonstop)
327 uint32_t ip = pinger->RecvPing();
331 std::multimap<uint32_t, time_t>::iterator treeIterUpper = pinger->pingIP.upper_bound(ip);
332 std::multimap<uint32_t, time_t>::iterator treeIterLower = pinger->pingIP.lower_bound(ip);
333 while (treeIterUpper != treeIterLower)
336 treeIterLower->second = stgTime;
338 treeIterLower->second = time(NULL);
345 pinger->isRunningRecver = false;
348 //-----------------------------------------------------------------------------