/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Author : Boris Mikhailenko */ /* $Revision: 1.23 $ $Date: 2010/04/22 12:57:46 $ $Author: faust $ */ #ifndef TRAFFCOUNTER_H #define TRAFFCOUNTER_H #include #include #include #include #include #include "os_int.h" #include "stg_logger.h" #include "raw_ip_packet.h" #include "users.h" #include "actions.h" #include "noncopyable.h" #include "eventloop.h" #define PROTOMAX (5) //----------------------------------------------------------------------------- struct RULE { uint32_t ip; // IP uint32_t mask; // Network mask uint16_t port1; // Min port uint16_t port2; // Max port uint8_t proto; // Protocol uint32_t dir; // Direction }; //----------------------------------------------------------------------------- struct PACKET_EXTRA_DATA { PACKET_EXTRA_DATA() : flushTime(0), updateTime(0), userU(), userUPresent(false), userD(), userDPresent(false), dirU(DIR_NUM), dirD(DIR_NUM), lenU(0), lenD(0) {}; PACKET_EXTRA_DATA(const PACKET_EXTRA_DATA & pp) : flushTime(pp.flushTime), updateTime(pp.updateTime), userU(pp.userU), userUPresent(pp.userUPresent), userD(pp.userD), userDPresent(pp.userDPresent), dirU(pp.dirU), dirD(pp.dirD), lenU(pp.lenU), lenD(pp.lenD) {}; time_t flushTime; // Last flush time time_t updateTime; // Last update time user_iter userU; // Uploader bool userUPresent; // Uploader is registered user user_iter userD; // Downloader bool userDPresent; // Downloader is registered user int dirU; // Upload direction int dirD; // Download direction uint32_t lenU; // Upload length uint32_t lenD; // Download length }; //----------------------------------------------------------------------------- class TRAFFCOUNTER; //----------------------------------------------------------------------------- class TRF_IP_BEFORE: public PROPERTY_NOTIFIER_BASE { public: TRF_IP_BEFORE(TRAFFCOUNTER & t, user_iter u) : PROPERTY_NOTIFIER_BASE(), traffCnt(t), user(u) {}; void Notify(const uint32_t & oldValue, const uint32_t & newValue); void SetUser(user_iter u) { user = u; } user_iter GetUser() const { return user; } private: TRAFFCOUNTER & traffCnt; user_iter user; }; //----------------------------------------------------------------------------- class TRF_IP_AFTER: public PROPERTY_NOTIFIER_BASE { public: TRF_IP_AFTER(TRAFFCOUNTER & t, user_iter u) : PROPERTY_NOTIFIER_BASE(), traffCnt(t), user(u) {}; void Notify(const uint32_t & oldValue, const uint32_t & newValue); void SetUser(user_iter u) { user = u; } user_iter GetUser() const { return user; } private: TRAFFCOUNTER & traffCnt; user_iter user; }; //----------------------------------------------------------------------------- class ADD_USER_NONIFIER: public NOTIFIER_BASE { public: ADD_USER_NONIFIER(TRAFFCOUNTER & t) : NOTIFIER_BASE(), traffCnt(t) {}; virtual ~ADD_USER_NONIFIER(){}; void Notify(const user_iter & user); private: TRAFFCOUNTER & traffCnt; }; //----------------------------------------------------------------------------- class DEL_USER_NONIFIER: public NOTIFIER_BASE { public: DEL_USER_NONIFIER(TRAFFCOUNTER & t) : NOTIFIER_BASE(), traffCnt(t) {}; virtual ~DEL_USER_NONIFIER(){}; void Notify(const user_iter & user); private: TRAFFCOUNTER & traffCnt; }; //----------------------------------------------------------------------------- class TRAFFCOUNTER : private NONCOPYABLE { friend class ADD_USER_NONIFIER; friend class DEL_USER_NONIFIER; friend class TRF_IP_BEFORE; friend class TRF_IP_AFTER; public: TRAFFCOUNTER(USERS * users, const TARIFFS * tariffs, const std::string & rulesFileName); ~TRAFFCOUNTER(); void SetRulesFile(const std::string & rulesFileName); int Reload(); int Start(); int Stop(); void Process(const RAW_PACKET & rawPacket); void SetMonitorDir(const std::string & monitorDir); private: bool ParseAddress(const char * ta, RULE * rule) const; uint32_t CalcMask(uint32_t msk) const; void FreeRules(); void PrintRule(RULE rule) const; bool ReadRules(bool test = false); static void * Run(void * data); void DeterminateDir(const RAW_PACKET & packet, int * dirU, // Direction for upload int * dirD) const; // Direction for download void FlushAndRemove(); void AddUser(user_iter user); void DelUser(uint32_t uip); void SetUserNotifiers(user_iter user); void UnSetUserNotifiers(user_iter user); std::list rules; typedef std::list::iterator rule_iter; std::map packets; // Packets tree typedef std::map::iterator pp_iter; std::multimap ip2packets; // IP-to-Packet index typedef std::multimap::iterator ip2p_iter; typedef std::multimap::const_iterator ip2p_citer; std::string dirName[DIR_NUM + 1]; STG_LOGGER & WriteServLog; std::string rulesFileName; std::string monitorDir; bool monitoring; USERS * users; bool running; bool stopped; pthread_mutex_t mutex; pthread_t thread; std::list ipBeforeNotifiers; std::list ipAfterNotifiers; ADD_USER_NONIFIER addUserNotifier; DEL_USER_NONIFIER delUserNotifier; }; //----------------------------------------------------------------------------- inline void TRF_IP_BEFORE::Notify(const uint32_t & oldValue, const uint32_t &) { // User changes his address. Remove old IP if (!oldValue) return; EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER::DelUser, oldValue); } //----------------------------------------------------------------------------- inline void TRF_IP_AFTER::Notify(const uint32_t &, const uint32_t & newValue) { // User changes his address. Add new IP if (!newValue) return; EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER::AddUser, user); } //----------------------------------------------------------------------------- inline void ADD_USER_NONIFIER::Notify(const user_iter & user) { EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER::SetUserNotifiers, user); } //----------------------------------------------------------------------------- inline void DEL_USER_NONIFIER::Notify(const user_iter & user) { EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER::UnSetUserNotifiers, user); EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TRAFFCOUNTER::DelUser, user->GetCurrIP()); } //----------------------------------------------------------------------------- #endif //TRAFFCOUNTER_H