]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/other/ping/ping.cpp
Документация помещена в каталог doc
[stg.git] / projects / stargazer / plugins / other / ping / ping.cpp
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <signal.h>
4
5 #include "ping.h"
6 #include "../../../user.h"
7
8 class PING_CREATOR
9 {
10 private:
11     PING * ping;
12
13 public:
14     PING_CREATOR()
15         : ping(new PING())
16         {
17         };
18     ~PING_CREATOR()
19         {
20         delete ping;
21         };
22
23     PING * GetPlugin()
24         {
25         return ping;
26         };
27 };
28 //-----------------------------------------------------------------------------
29 //-----------------------------------------------------------------------------
30 //-----------------------------------------------------------------------------
31 PING_CREATOR pc;
32 //-----------------------------------------------------------------------------
33 //-----------------------------------------------------------------------------
34 //-----------------------------------------------------------------------------
35 // ëÌÁÓÓ ÄÌÑ ÐÏÉÓËÁ ÀÚÅÒÁ × ÓÐÉÓËÅ ÎÏÔÉÆÉËÁÔÏÒÏ×
36 template <typename varType>
37 class IS_CONTAINS_USER: public binary_function<varType, user_iter, bool>
38 {
39 public:
40     bool operator()(varType notifier, user_iter user) const
41         {
42         return notifier.GetUser() == user;
43         };
44 };
45 //-----------------------------------------------------------------------------
46 //-----------------------------------------------------------------------------
47 //-----------------------------------------------------------------------------
48 BASE_PLUGIN * GetPlugin()
49 {
50 return pc.GetPlugin();
51 }
52 //-----------------------------------------------------------------------------
53 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
55 PING_SETTINGS::PING_SETTINGS()
56     : pingDelay(0),
57       errorStr()
58 {
59 }
60 //-----------------------------------------------------------------------------
61 int PING_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
62 {
63 PARAM_VALUE pv;
64 vector<PARAM_VALUE>::const_iterator pvi;
65
66 pv.param = "PingDelay";
67 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
68 if (pvi == s.moduleParams.end())
69     {
70     errorStr = "Parameter \'PingDelay\' not found.";
71     printfd(__FILE__, "Parameter 'PingDelay' not found\n");
72     return -1;
73     }
74 if (ParseIntInRange(pvi->value[0], 5, 3600, &pingDelay))
75     {
76     errorStr = "Cannot parse parameter \'PingDelay\': " + errorStr;
77     printfd(__FILE__, "Canot parse parameter 'PingDelay'\n");
78     return -1;
79     }
80
81 return 0;
82 }
83 //-----------------------------------------------------------------------------
84 int PING_SETTINGS::ParseIntInRange(const string & str, int min, int max, int * val)
85 {
86 if (str2x(str.c_str(), *val))
87     {
88     errorStr = "Incorrect value \'" + str + "\'.";
89     return -1;
90     }
91 if (*val < min || *val > max)
92     {
93     errorStr = "Value \'" + str + "\' out of range.";
94     return -1;
95     }
96 return 0;
97 }
98 //-----------------------------------------------------------------------------
99 PING::PING()
100 {
101 pthread_mutex_init(&mutex, NULL);
102 isRunning = false;
103 }
104 //-----------------------------------------------------------------------------
105 PING::~PING()
106 {
107 pthread_mutex_destroy(&mutex);
108 }
109 //-----------------------------------------------------------------------------
110 const string PING::GetVersion() const
111 {
112 return "Pinger v.1.01";
113 }
114 //-----------------------------------------------------------------------------
115 void PING::SetSettings(const MODULE_SETTINGS & s)
116 {
117 settings = s;
118 }
119 //-----------------------------------------------------------------------------
120 int PING::ParseSettings()
121 {
122 int ret = pingSettings.ParseSettings(settings);
123 if (ret)
124     errorStr = pingSettings.GetStrError();
125 return ret;
126 }
127 //-----------------------------------------------------------------------------
128 void PING::SetUsers(USERS * u)
129 {
130 users = u;
131 }
132 //-----------------------------------------------------------------------------
133 const string & PING::GetStrError() const
134 {
135 return errorStr;
136 }
137 //-----------------------------------------------------------------------------
138 int PING::Start()
139 {
140 GetUsers();
141
142 onAddUserNotifier.SetPinger(this);
143 onDelUserNotifier.SetPinger(this);
144 users->AddNotifierUserAdd(&onAddUserNotifier);
145 users->AddNotifierUserDel(&onDelUserNotifier);
146
147 nonstop = true;
148
149 pinger.SetDelayTime(pingSettings.GetPingDelay());
150 pinger.Start();
151
152 if (pthread_create(&thread, NULL, Run, this))
153     {
154     errorStr = "Cannot start thread.";
155     printfd(__FILE__, "Cannot start thread\n");
156     return -1;
157     }
158
159 return 0;
160 }
161 //-----------------------------------------------------------------------------
162 int PING::Stop()
163 {
164 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
165
166 if (!isRunning)
167     return 0;
168
169 pinger.Stop();
170 nonstop = false;
171 //5 seconds to thread stops itself
172 for (int i = 0; i < 25; i++)
173     {
174     if (!isRunning)
175         break;
176
177     usleep(200000);
178     }
179
180 //after 5 seconds waiting thread still running. now kill it
181 if (isRunning)
182     {
183     printfd(__FILE__, "kill PING thread.\n");
184     if (pthread_kill(thread, SIGINT))
185         {
186         errorStr = "Cannot kill PING thread.";
187         printfd(__FILE__, "Cannot kill PING thread.\n");
188         return -1;
189         }
190     printfd(__FILE__, "PING killed\n");
191     }
192
193 users->DelNotifierUserAdd(&onAddUserNotifier);
194 users->DelNotifierUserDel(&onDelUserNotifier);
195
196 list<user_iter>::iterator users_iter;
197 users_iter = usersList.begin();
198 while (users_iter != usersList.end())
199     {
200     UnSetUserNotifiers(*users_iter);
201     users_iter++;
202     }
203
204 return 0;
205 }
206 //-----------------------------------------------------------------------------
207 bool PING::IsRunning()
208 {
209 return isRunning;
210 }
211 //-----------------------------------------------------------------------------
212 void * PING::Run(void * d)
213 {
214 PING * ping = (PING*)d;
215 ping->isRunning = true;
216 list<user_iter>::iterator iter;
217 uint32_t ip;
218 time_t t;
219
220 while (ping->nonstop)
221     {
222     iter = ping->usersList.begin();
223         {
224         STG_LOCKER lock(&ping->mutex, __FILE__, __LINE__);
225         while (iter != ping->usersList.end())
226             {
227             if ((*iter)->property.ips.ConstData().OnlyOneIP())
228                 {
229                 ip = (*iter)->property.ips.ConstData()[0].ip;
230                 if (ping->pinger.GetIPTime(ip, &t) == 0)
231                     {
232                     if (t)
233                         (*iter)->UpdatePingTime(t);
234                     }
235                 }
236             else
237                 {
238                 ip = (*iter)->GetCurrIP();
239                 if (ip)
240                     {
241                     if (ping->pinger.GetIPTime(ip, &t) == 0)
242                         {
243                         if (t)
244                             (*iter)->UpdatePingTime(t);
245                         }
246                     }
247                 }
248             iter++;
249             }
250         }
251     for (int i = 0; i < 100; i++)
252         {
253         if (ping->nonstop)
254             {
255             usleep((10000*ping->pingSettings.GetPingDelay())/3 + 50000);
256             }
257         }
258     }
259 ping->isRunning = false;
260 return NULL;
261 }
262 //-----------------------------------------------------------------------------
263 uint16_t PING::GetStartPosition() const
264 {
265 return 100;
266 }
267 //-----------------------------------------------------------------------------
268 uint16_t PING::GetStopPosition() const
269 {
270 return 100;
271 }
272 //-----------------------------------------------------------------------------
273 void PING::SetUserNotifiers(user_iter u)
274 {
275 CHG_CURRIP_NOTIFIER_PING    ChgCurrIPNotifier;
276 CHG_IPS_NOTIFIER_PING       ChgIPNotifier;
277
278 ChgCurrIPNotifier.SetPinger(this);
279 ChgCurrIPNotifier.SetUser(u);
280 ChgCurrIPNotifierList.push_front(ChgCurrIPNotifier);
281
282 ChgIPNotifier.SetPinger(this);
283 ChgIPNotifier.SetUser(u);
284 ChgIPNotifierList.push_front(ChgIPNotifier);
285
286 u->AddCurrIPAfterNotifier(&(*ChgCurrIPNotifierList.begin()));
287 u->property.ips.AddAfterNotifier(&(*ChgIPNotifierList.begin()));
288 }
289 //-----------------------------------------------------------------------------
290 void PING::UnSetUserNotifiers(user_iter u)
291 {
292 // ---          CurrIP              ---
293 IS_CONTAINS_USER<CHG_CURRIP_NOTIFIER_PING>   IsContainsUserCurrIP;
294 IS_CONTAINS_USER<CHG_IPS_NOTIFIER_PING>      IsContainsUserIP;
295
296 list<CHG_CURRIP_NOTIFIER_PING>::iterator     currIPter;
297 list<CHG_IPS_NOTIFIER_PING>::iterator        IPIter;
298
299 currIPter = find_if(ChgCurrIPNotifierList.begin(),
300                     ChgCurrIPNotifierList.end(),
301                     bind2nd(IsContainsUserCurrIP, u));
302
303 if (currIPter != ChgCurrIPNotifierList.end())
304     {
305     currIPter->GetUser()->DelCurrIPAfterNotifier(&(*currIPter));
306     ChgCurrIPNotifierList.erase(currIPter);
307     }
308 // ---         CurrIP end          ---
309
310 // ---          IP              ---
311 IPIter = find_if(ChgIPNotifierList.begin(),
312                  ChgIPNotifierList.end(),
313                  bind2nd(IsContainsUserIP, u));
314
315 if (IPIter != ChgIPNotifierList.end())
316     {
317     IPIter->GetUser()->property.ips.DelAfterNotifier(&(*IPIter));
318     ChgIPNotifierList.erase(IPIter);
319     }
320 // ---          IP end          ---
321 }
322 //-----------------------------------------------------------------------------
323 void PING::GetUsers()
324 {
325 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
326
327 user_iter u;
328 int h = users->OpenSearch();
329 if (!h)
330     {
331     printfd(__FILE__, "users->OpenSearch() error\n");
332     return;
333     }
334
335 while (users->SearchNext(h, &u) == 0)
336     {
337     usersList.push_back(u);
338     SetUserNotifiers(u);
339     if (u->property.ips.ConstData().OnlyOneIP())
340         {
341         pinger.AddIP(u->property.ips.ConstData()[0].ip);
342         }
343     else
344         {
345         uint32_t ip = u->GetCurrIP();
346         if (ip)
347             {
348             pinger.AddIP(ip);
349             }
350         }
351     }
352
353 users->CloseSearch(h);
354 }
355 //-----------------------------------------------------------------------------
356 void PING::AddUser(user_iter u)
357 {
358 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
359
360 SetUserNotifiers(u);
361 usersList.push_back(u);
362 }
363 //-----------------------------------------------------------------------------
364 void PING::DelUser(user_iter u)
365 {
366 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
367
368 UnSetUserNotifiers(u);
369
370 list<user_iter>::iterator users_iter;
371 users_iter = usersList.begin();
372
373 while (users_iter != usersList.end())
374     {
375     if (u == *users_iter)
376         {
377         usersList.erase(users_iter);
378         break;
379         }
380     users_iter++;
381     }
382 }
383 //-----------------------------------------------------------------------------
384 void CHG_CURRIP_NOTIFIER_PING::Notify(const uint32_t & oldIP, const uint32_t & newIP)
385 {
386 ping->pinger.DelIP(oldIP);
387 if (newIP)
388     {
389     ping->pinger.AddIP(newIP);
390     }
391 }
392 //-----------------------------------------------------------------------------
393 void CHG_IPS_NOTIFIER_PING::Notify(const USER_IPS & oldIPS, const USER_IPS & newIPS)
394 {
395 if (oldIPS.OnlyOneIP())
396     {
397     ping->pinger.DelIP(oldIPS[0].ip);
398     }
399
400 if (newIPS.OnlyOneIP())
401     {
402     ping->pinger.AddIP(newIPS[0].ip);
403     }
404 }
405 //-----------------------------------------------------------------------------
406 void ADD_USER_NONIFIER_PING::Notify(const user_iter & user)
407 {
408 ping->AddUser(user);
409 }
410 //-----------------------------------------------------------------------------
411 void DEL_USER_NONIFIER_PING::Notify(const user_iter & user)
412 {
413 ping->DelUser(user);
414 }
415 //-----------------------------------------------------------------------------
416
417
418
419
420
421