6 #include <sys/socket.h>
7 #include <netinet/in.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);
37 //-----------------------------------------------------------------------------
38 STG_PINGER::~STG_PINGER()
40 pthread_mutex_destroy(&mutex);
42 //-----------------------------------------------------------------------------
43 int STG_PINGER::Start()
45 struct protoent *proto = NULL;
46 proto = getprotobyname("ICMP");
47 sendSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
48 recvSocket = socket(PF_INET, SOCK_RAW, proto->p_proto);
50 pid = (int) getpid() % 65535;
51 if (sendSocket < 0 || recvSocket < 0)
53 errorStr = "Cannot create socket.";
57 if (pthread_create(&sendThread, NULL, RunSendPing, this))
59 errorStr = "Cannot create send thread.";
63 if (pthread_create(&recvThread, NULL, RunRecvPing, this))
65 errorStr = "Cannot create recv thread.";
71 //-----------------------------------------------------------------------------
72 int STG_PINGER::Stop()
78 //5 seconds to thread stops itself
79 for (size_t i = 0; i < 25; i++)
82 SendPing(0x0100007f);//127.0.0.1
90 //after 5 seconds waiting thread still running. now killing it
93 if (pthread_kill(recvThread, SIGINT))
95 errorStr = "Cannot kill thread.";
103 //5 seconds to thread stops itself
104 for (size_t i = 0; i < 25; i++)
106 if (!isRunningSender)
112 //after 5 seconds waiting thread still running. now killing it
115 if (pthread_kill(sendThread, SIGINT))
117 errorStr = "Cannot kill thread.";
126 //-----------------------------------------------------------------------------
127 void STG_PINGER::AddIP(uint32_t ip)
129 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
130 ipToAdd.push_back(ip);
132 //-----------------------------------------------------------------------------
133 void STG_PINGER::DelIP(uint32_t ip)
135 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
136 ipToDel.push_back(ip);
138 //-----------------------------------------------------------------------------
139 void STG_PINGER::RealAddIP()
141 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
143 std::list<uint32_t>::iterator iter;
144 iter = ipToAdd.begin();
145 while (iter != ipToAdd.end())
147 pingIP.insert(std::make_pair(*iter, 0));
150 ipToAdd.erase(ipToAdd.begin(), ipToAdd.end());
152 //-----------------------------------------------------------------------------
153 void STG_PINGER::RealDelIP()
155 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
157 std::list<uint32_t>::iterator iter;
158 std::multimap<uint32_t, time_t>::iterator treeIter;
159 iter = ipToDel.begin();
160 while (iter != ipToDel.end())
162 treeIter = pingIP.find(*iter);
163 if (treeIter != pingIP.end())
164 pingIP.erase(treeIter);
168 ipToDel.erase(ipToDel.begin(), ipToDel.end());
170 //-----------------------------------------------------------------------------
171 int STG_PINGER::GetPingIPNum() const
173 return pingIP.size();
175 //-----------------------------------------------------------------------------
176 void STG_PINGER::PrintAllIP()
178 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
179 std::multimap<uint32_t, time_t>::iterator iter;
180 iter = pingIP.begin();
181 while (iter != pingIP.end())
183 uint32_t ip = iter->first;
184 time_t t = iter->second;
187 printf("ip = %s, time = %9s\n", inet_ntostring(ip).c_str(), s.c_str());
192 //-----------------------------------------------------------------------------
193 int STG_PINGER::GetIPTime(uint32_t ip, time_t * t) const
195 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
196 std::multimap<uint32_t, time_t>::const_iterator treeIter;
198 treeIter = pingIP.find(ip);
199 if (treeIter == pingIP.end())
202 *t = treeIter->second;
205 //-----------------------------------------------------------------------------
206 uint16_t STG_PINGER::PingCheckSum(void * data, int len)
208 unsigned short * buf = (unsigned short *)data;
209 unsigned int sum = 0;
210 unsigned short result;
212 for ( sum = 0; len > 1; len -= 2 )
216 sum += *(unsigned char*)buf;
218 sum = (sum >> 16) + (sum & 0xFFFF);
223 //-----------------------------------------------------------------------------
224 int STG_PINGER::SendPing(uint32_t ip)
226 struct sockaddr_in addr;
227 memset(&addr, 0, sizeof(addr));
228 addr.sin_family = AF_INET;
230 addr.sin_addr.s_addr = ip;
232 memset(&pmSend, 0, sizeof(pmSend));
233 pmSend.hdr.type = ICMP_ECHO;
234 pmSend.hdr.un.echo.id = pid;
235 memcpy(pmSend.msg, &ip, sizeof(ip));
237 pmSend.hdr.checksum = PingCheckSum(&pmSend, sizeof(pmSend));
239 if (sendto(sendSocket, &pmSend, sizeof(pmSend), 0, (sockaddr *)&addr, sizeof(addr)) <= 0 )
241 errorStr = "Send ping error: " + std::string(strerror(errno));
248 //-----------------------------------------------------------------------------
249 uint32_t STG_PINGER::RecvPing()
251 struct sockaddr_in addr;
255 memset(buf, 0, sizeof(buf));
257 socklen_t len = sizeof(addr);
259 bytes = recvfrom(recvSocket, &buf, sizeof(buf), 0, (struct sockaddr*)&addr, &len);
262 struct IP_HDR * ip = (struct IP_HDR *)buf;
263 struct ICMP_HDR *icmp = (struct ICMP_HDR *)(buf + ip->ihl * 4);
265 if (icmp->un.echo.id != pid)
268 ipAddr = *(uint32_t*)(buf + sizeof(ICMP_HDR) + ip->ihl * 4);
273 //-----------------------------------------------------------------------------
274 void * STG_PINGER::RunSendPing(void * d)
276 STG_PINGER * pinger = (STG_PINGER*)d;
278 pinger->isRunningSender = true;
280 while (pinger->nonstop)
285 std::multimap<uint32_t, time_t>::iterator iter;
286 iter = pinger->pingIP.begin();
287 while (iter != pinger->pingIP.end())
289 pinger->SendPing(iter->first);
299 currTime = lastPing = time(NULL);
302 while (currTime - lastPing < pinger->delay && pinger->nonstop)
307 currTime = time(NULL);
313 pinger->isRunningSender = false;
317 //-----------------------------------------------------------------------------
318 void * STG_PINGER::RunRecvPing(void * d)
320 STG_PINGER * pinger = (STG_PINGER*)d;
322 pinger->isRunningRecver = true;
325 std::multimap<uint32_t, time_t>::iterator treeIterLower;
326 std::multimap<uint32_t, time_t>::iterator treeIterUpper;
328 while (pinger->nonstop)
330 ip = pinger->RecvPing();
334 treeIterUpper = pinger->pingIP.upper_bound(ip);
335 treeIterLower = pinger->pingIP.lower_bound(ip);
337 while (treeIterUpper != treeIterLower)
340 treeIterLower->second = stgTime;
342 treeIterLower->second = time(NULL);
350 pinger->isRunningRecver = false;
353 //-----------------------------------------------------------------------------