2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
27 $Date: 2010/09/13 05:56:42 $
44 #include "users_impl.h"
46 #include "stg_timer.h"
50 extern const volatile time_t stgTime;
52 //#define USERS_DEBUG 1
54 //-----------------------------------------------------------------------------
55 USERS_IMPL::USERS_IMPL(SETTINGS_IMPL * s, STORE * st, TARIFFS * t, const ADMIN * sa)
58 userIPNotifiersBefore(),
59 userIPNotifiersAfter(),
66 WriteServLog(GetStgLogger()),
76 pthread_mutexattr_t attr;
77 pthread_mutexattr_init(&attr);
78 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
79 pthread_mutex_init(&mutex, &attr);
81 //-----------------------------------------------------------------------------
82 USERS_IMPL::~USERS_IMPL()
84 pthread_mutex_destroy(&mutex);
86 //-----------------------------------------------------------------------------
87 int USERS_IMPL::FindByNameNonLock(const string & login, user_iter * user)
89 map<string, user_iter>::iterator iter;
90 iter = loginIndex.find(login);
91 if (iter != loginIndex.end())
99 //-----------------------------------------------------------------------------
100 int USERS_IMPL::FindByName(const string & login, USER_PTR * user)
102 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
104 int res = FindByNameNonLock(login, &u);
110 //-----------------------------------------------------------------------------
111 bool USERS_IMPL::TariffInUse(const string & tariffName) const
113 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
114 list<USER_IMPL>::const_iterator iter;
115 iter = users.begin();
116 while (iter != users.end())
118 if (iter->GetProperty().tariffName.Get() == tariffName)
124 //-----------------------------------------------------------------------------
125 int USERS_IMPL::Add(const string & login, const ADMIN * admin)
127 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
128 const PRIV * priv = admin->GetPriv();
130 if (!priv->userAddDel)
132 WriteServLog("%s tried to add user \'%s\'. Access denied.",
133 admin->GetLogStr().c_str(), login.c_str());
134 /*errorStr = "Admin \'" + admin->GetLogin() +
135 "\': tried to add user \'" + ud->login + "\'. Access denied.";*/
140 if (store->AddUser(login))
143 //WriteServLog("Admin \'%s\': tried to add user \'%s\'. Access denied.",
144 // admin->GetLogin().c_str(), ud->login.c_str());
149 USER_IMPL u(settings, store, tariffs, sysAdmin, this);
160 if (settings->GetDayResetTraff() > tms->tm_mday)
163 tms->tm_mday = settings->GetDayResetTraff();*/
167 u.SetPassiveTimeAsNewUser();
172 WriteServLog("%s User \'%s\' added.",
173 admin->GetLogStr().c_str(), login.c_str());
179 AddUserIntoIndexes(users.begin());
180 SetUserNotifiers(users.begin());
182 // õ×ÅÄÏÍÌÑÅÍ ×ÓÅÈ ÖÅÌÁÀÝÉÈ, ÞÔÏ ÄÏÂÁ×ÌÅÎ ÎÏ×ÙÊ ÐÏÌØÚÏ×ÁÔÅÌØ
183 set<NOTIFIER_BASE<USER_PTR> *>::iterator ni = onAddNotifiers.begin();
184 while (ni != onAddNotifiers.end())
186 (*ni)->Notify(&users.front());
192 //-----------------------------------------------------------------------------
193 void USERS_IMPL::Del(const string & login, const ADMIN * admin)
195 const PRIV * priv = admin->GetPriv();
198 if (!priv->userAddDel)
200 WriteServLog("%s tried to remove user \'%s\'. Access denied.",
201 admin->GetLogStr().c_str(), login.c_str());
207 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
209 if (FindByNameNonLock(login, &u))
211 WriteServLog("%s tried to delete user \'%s\': not found.",
212 admin->GetLogStr().c_str(),
218 set<NOTIFIER_BASE<USER_PTR> *>::iterator ni = onDelNotifiers.begin();
219 while (ni != onDelNotifiers.end())
221 (*ni)->Notify(&(*u));
226 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
233 utd.delTime = stgTime;
234 usersToDelete.push_back(utd);
236 UnSetUserNotifiers(u);
237 DelUserFromIndexes(u);
239 WriteServLog("%s User \'%s\' deleted.",
240 admin->GetLogStr().c_str(), login.c_str());
244 //-----------------------------------------------------------------------------
245 int USERS_IMPL::ReadUsers()
247 vector<string> usersList;
249 if (store->GetUsersList(&usersList) < 0)
251 WriteServLog(store->GetStrError().c_str());
257 for (unsigned int i = 0; i < usersList.size(); i++)
259 USER_IMPL u(settings, store, tariffs, sysAdmin, this);
261 u.SetLogin(usersList[i]);
265 AddUserIntoIndexes(ui);
266 SetUserNotifiers(ui);
268 if (ui->ReadConf() < 0)
271 if (ui->ReadStat() < 0)
277 //-----------------------------------------------------------------------------
278 void * USERS_IMPL::Run(void * d)
280 printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
281 USERS_IMPL * us = (USERS_IMPL*) d;
285 localtime_r(&tt, &t);
290 printfd(__FILE__,"Day = %d Min = %d\n", day, min);
292 time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
293 string monFile = us->settings->GetMonitorDir() + "/users_r";
294 printfd(__FILE__, "Monitor=%d file USERS %s\n", us->settings->GetMonitoring(), monFile.c_str());
296 us->isRunning = true;
299 //printfd(__FILE__,"New Minute. old = %02d current = %02d\n", min, t->tm_min);
300 //printfd(__FILE__,"New Day. old = %2d current = %2d\n", day, t->tm_mday);
302 for_each(us->users.begin(), us->users.end(), mem_fun_ref(&USER_IMPL::Run));
305 localtime_r(&tt, &t);
309 printfd(__FILE__,"Sec = %d\n", stgTime);
310 printfd(__FILE__,"New Minute. old = %d current = %d\n", min, t.tm_min);
316 if (day != t.tm_mday)
318 printfd(__FILE__,"Sec = %d\n", stgTime);
319 printfd(__FILE__,"New Day. old = %d current = %d\n", day, t.tm_mday);
324 if (us->settings->GetMonitoring() && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
326 //printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
328 TouchFile(monFile.c_str());
332 } //while (us->nonstop)
334 user_iter ui = us->users.begin();
335 while (ui != us->users.end())
337 us->UnSetUserNotifiers(ui);
338 us->DelUserFromIndexes(ui);
342 list<USER_TO_DEL>::iterator iter;
343 iter = us->usersToDelete.begin();
344 while (iter != us->usersToDelete.end())
346 iter->delTime -= 2 * userDeleteDelayTime;
351 us->isRunning = false;
355 //-----------------------------------------------------------------------------
356 void USERS_IMPL::NewMinute(const struct tm & t)
358 //Write traff, reset session traff. Fake disconnect-connect
359 if (t.tm_hour == 23 && t.tm_min == 59)
361 printfd(__FILE__,"MidnightResetSessionStat\n");
362 for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::MidnightResetSessionStat));
365 if (TimeToWriteDetailStat(t))
367 //printfd(__FILE__, "USER::WriteInetStat\n");
370 // ðÉÛÅÍ ÀÚÅÒÏ× ÞÁÓÔÑÍÉ. ÷ ÐÅÒÅÒÙ×ÁÈ ×ÙÚÙ×ÁÅÍ USER::Run
371 list<USER_IMPL>::iterator usr = users.begin();
372 while (usr != users.end())
375 usr->WriteDetailStat();
377 if (usersCnt % 10 == 0)
378 for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::Run));
384 //-----------------------------------------------------------------------------
385 void USERS_IMPL::NewDay(const struct tm & t)
389 localtime_r(&tt, &t1);
390 int dayFee = settings->GetDayFee();
393 dayFee = DaysInCurrentMonth();
395 printfd(__FILE__, "DayFee = %d\n", dayFee);
396 printfd(__FILE__, "Today = %d DayResetTraff = %d\n", t1.tm_mday, settings->GetDayResetTraff());
397 printfd(__FILE__, "DayFeeIsLastDay = %d\n", settings->GetDayFeeIsLastDay());
399 if (!settings->GetDayFeeIsLastDay())
401 printfd(__FILE__, "DayResetTraff - 1 -\n");
403 //printfd(__FILE__, "DayResetTraff - 1 - 1 -\n");
406 if (settings->GetSpreadFee())
408 printfd(__FILE__, "Spread DayFee\n");
409 for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::ProcessDayFeeSpread));
413 if (t.tm_mday == dayFee)
415 printfd(__FILE__, "DayFee\n");
416 for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::ProcessDayFee));
420 if (settings->GetDayFeeIsLastDay())
422 printfd(__FILE__, "DayResetTraff - 2 -\n");
426 //-----------------------------------------------------------------------------
427 void USERS_IMPL::DayResetTraff(const struct tm & t1)
429 int dayResetTraff = settings->GetDayResetTraff();
430 if (dayResetTraff == 0)
431 dayResetTraff = DaysInCurrentMonth();
432 if (t1.tm_mday == dayResetTraff)
434 printfd(__FILE__, "ResetTraff\n");
435 for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::ProcessNewMonth));
436 for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::SetPrepaidTraff));
439 //-----------------------------------------------------------------------------
440 int USERS_IMPL::Start()
444 WriteServLog("USERS: Error: Cannot read users!");
449 if (pthread_create(&thread, NULL, Run, this))
451 WriteServLog("USERS: Error: Cannot start thread!");
456 //-----------------------------------------------------------------------------
457 int USERS_IMPL::Stop()
459 printfd(__FILE__, "USERS::Stop()\n");
463 //printfd(__FILE__, "Alredy stopped\n");
469 //5 seconds to thread stops itself
470 struct timespec ts = {0, 200000000};
471 for (size_t i = 0; i < 25 * (users.size() / 50 + 1); i++)
476 nanosleep(&ts, NULL);
479 //after 5 seconds waiting thread still running. now kill it
482 printfd(__FILE__, "kill USERS thread.\n");
483 //TODO pthread_cancel()
484 if (pthread_kill(thread, SIGINT))
486 //errorStr = "Cannot kill USERS thread.";
487 //printfd(__FILE__, "Cannot kill USERS thread.\n");
490 printfd(__FILE__, "USERS killed\n");
493 printfd(__FILE__, "Before USERS::Run()\n");
494 for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::Run));
496 // 'cause bind2st accepts only constant first param
497 for (list<USER_IMPL>::iterator it = users.begin();
500 it->WriteDetailStat(true);
502 for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::WriteStat));
503 for_each(users.begin(), users.end(), mem_fun_ref(&USER_IMPL::WriteConf));
505 printfd(__FILE__, "USERS::Stop()\n");
508 //-----------------------------------------------------------------------------
509 void USERS_IMPL::RealDelUser()
511 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
513 printfd(__FILE__, "RealDelUser() users to del: %d\n", usersToDelete.size());
515 list<USER_TO_DEL>::iterator iter;
516 iter = usersToDelete.begin();
517 while (iter != usersToDelete.end())
519 printfd(__FILE__, "RealDelUser() user=%s\n", iter->iter->GetLogin().c_str());
520 if (iter->delTime + userDeleteDelayTime < stgTime)
522 printfd(__FILE__, "RealDelUser() user=%s removed from DB\n", iter->iter->GetLogin().c_str());
523 if (store->DelUser(iter->iter->GetLogin()))
525 WriteServLog("Error removing user \'%s\' from database.", iter->iter->GetLogin().c_str());
527 users.erase(iter->iter);
528 usersToDelete.erase(iter++);
537 //-----------------------------------------------------------------------------
538 int USERS_IMPL::GetUserNum() const
542 //-----------------------------------------------------------------------------
543 void USERS_IMPL::AddToIPIdx(user_iter user)
545 printfd(__FILE__, "USERS: Add IP Idx\n");
546 uint32_t ip = user->GetCurrIP();
547 //assert(ip && "User has non-null ip");
549 return; // User has disconnected
551 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
553 const map<uint32_t, user_iter>::iterator it(
554 ipIndex.lower_bound(ip)
557 assert((it == ipIndex.end() || it->first != ip) && "User is not in index");
559 ipIndex.insert(it, std::make_pair(ip, user));
561 //-----------------------------------------------------------------------------
562 void USERS_IMPL::DelFromIPIdx(uint32_t ip)
564 printfd(__FILE__, "USERS: Del IP Idx\n");
565 assert(ip && "User has non-null ip");
567 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
569 const map<uint32_t, user_iter>::iterator it(
573 //assert(it != ipIndex.end() && "User is in index");
574 if (it == ipIndex.end())
575 return; // User has not been added
579 //-----------------------------------------------------------------------------
580 int USERS_IMPL::FindByIPIdx(uint32_t ip, USER_PTR * usr) const
582 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
584 map<uint32_t, user_iter>::const_iterator it;
585 it = ipIndex.find(ip);
587 if (it == ipIndex.end())
589 //printfd(__FILE__, "User NOT found in IP_Index!!!\n");
592 *usr = &(*it->second);
593 //printfd(__FILE__, "User found in IP_Index\n");
596 //-----------------------------------------------------------------------------
597 bool USERS_IMPL::IsIPInIndex(uint32_t ip) const
599 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
601 map<uint32_t, user_iter>::const_iterator it;
602 it = ipIndex.find(ip);
604 return it != ipIndex.end();
606 //-----------------------------------------------------------------------------
607 void USERS_IMPL::AddNotifierUserAdd(NOTIFIER_BASE<USER_PTR> * n)
609 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
610 onAddNotifiers.insert(n);
612 //-----------------------------------------------------------------------------
613 void USERS_IMPL::DelNotifierUserAdd(NOTIFIER_BASE<USER_PTR> * n)
615 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
616 //printfd(__FILE__, "DelNotifierUserAdd\n");
617 onAddNotifiers.erase(n);
619 //-----------------------------------------------------------------------------
620 void USERS_IMPL::AddNotifierUserDel(NOTIFIER_BASE<USER_PTR> * n)
622 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
623 onDelNotifiers.insert(n);
625 //-----------------------------------------------------------------------------
626 void USERS_IMPL::DelNotifierUserDel(NOTIFIER_BASE<USER_PTR> * n)
628 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
629 onDelNotifiers.erase(n);
631 //-----------------------------------------------------------------------------
632 int USERS_IMPL::OpenSearch()
634 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
636 searchDescriptors[handle] = users.begin();
639 //-----------------------------------------------------------------------------
640 int USERS_IMPL::SearchNext(int h, USER_PTR * user)
642 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
644 if (searchDescriptors.find(h) == searchDescriptors.end())
646 WriteServLog("USERS. Incorrect search handle.");
650 if (searchDescriptors[h] == users.end())
653 while (searchDescriptors[h]->GetDeleted())
655 ++searchDescriptors[h];
656 if (searchDescriptors[h] == users.end())
662 *user = &(*searchDescriptors[h]);
664 ++searchDescriptors[h];
668 //-----------------------------------------------------------------------------
669 int USERS_IMPL::CloseSearch(int h)
671 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
672 if (searchDescriptors.find(h) != searchDescriptors.end())
674 searchDescriptors.erase(searchDescriptors.find(h));
678 WriteServLog("USERS. Incorrect search handle.");
681 //-----------------------------------------------------------------------------
682 void USERS_IMPL::SetUserNotifiers(user_iter user)
684 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
686 PROPERTY_NOTIFER_IP_BEFORE nb(*this, user);
687 PROPERTY_NOTIFER_IP_AFTER na(*this, user);
689 userIPNotifiersBefore.push_front(nb);
690 userIPNotifiersAfter.push_front(na);
692 user->AddCurrIPBeforeNotifier(&(*userIPNotifiersBefore.begin()));
693 user->AddCurrIPAfterNotifier(&(*userIPNotifiersAfter.begin()));
695 //-----------------------------------------------------------------------------
696 void USERS_IMPL::UnSetUserNotifiers(user_iter user)
698 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
700 list<PROPERTY_NOTIFER_IP_BEFORE>::iterator bi;
701 list<PROPERTY_NOTIFER_IP_AFTER>::iterator ai;
703 bi = userIPNotifiersBefore.begin();
704 while (bi != userIPNotifiersBefore.end())
706 if (bi->GetUser() == user)
708 bi->GetUser()->DelCurrIPBeforeNotifier(&(*bi));
709 userIPNotifiersBefore.erase(bi);
710 //printfd(__FILE__, "Notifier Before removed. User %s\n", bi->GetUser()->GetLogin().c_str());
716 ai = userIPNotifiersAfter.begin();
717 while (ai != userIPNotifiersAfter.end())
719 if (ai->GetUser() == user)
721 ai->GetUser()->DelCurrIPAfterNotifier(&(*ai));
722 userIPNotifiersAfter.erase(ai);
723 //printfd(__FILE__, "Notifier After removed. User %s\n", ai->GetUser()->GetLogin().c_str());
729 //-----------------------------------------------------------------------------
730 void USERS_IMPL::AddUserIntoIndexes(user_iter user)
732 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
733 loginIndex.insert(make_pair(user->GetLogin(), user));
735 //-----------------------------------------------------------------------------
736 void USERS_IMPL::DelUserFromIndexes(user_iter user)
738 STG_LOCKER lock(&mutex, __FILE__, __LINE__);
739 loginIndex.erase(user->GetLogin());
741 //-----------------------------------------------------------------------------
742 bool USERS_IMPL::TimeToWriteDetailStat(const struct tm & t)
744 int statTime = settings->GetDetailStatWritePeriod();
753 if (t.tm_min % 30 == 0)
757 if (t.tm_min % 15 == 0)
761 if (t.tm_min % 10 == 0)