From f7805a596d2e7c451b997701ee21305a7fe23698 Mon Sep 17 00:00:00 2001 From: Maxim Mamontov Date: Sun, 2 Dec 2012 16:50:41 +0200 Subject: [PATCH] Fixed problems with connect/disconnect notification. --- .../plugins/other/rscript/rscript.cpp | 137 ++++++++++-------- .../stargazer/plugins/other/rscript/rscript.h | 67 ++++++--- .../plugins/other/rscript/ur_functor.h | 10 +- 3 files changed, 124 insertions(+), 90 deletions(-) diff --git a/projects/stargazer/plugins/other/rscript/rscript.cpp b/projects/stargazer/plugins/other/rscript/rscript.cpp index ebe2556d..82ca4f5d 100644 --- a/projects/stargazer/plugins/other/rscript/rscript.cpp +++ b/projects/stargazer/plugins/other/rscript/rscript.cpp @@ -44,6 +44,19 @@ extern volatile const time_t stgTime; using RS::REMOTE_SCRIPT; +namespace { + +template +struct USER_IS +{ + USER_IS(USER_PTR u) : user(u) {} + bool operator()(const T & notifier) { return notifier.GetUser() == user; } + + USER_PTR user; +}; + +} // namespace anonymous + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -58,34 +71,6 @@ return rsc.GetPlugin(); //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -RS::USER::USER(const std::vector & r, USER_PTR it, REMOTE_SCRIPT & rs) - : lastSentTime(0), - user(it), - routers(r), - shortPacketsCount(0), - ip(user->GetCurrIP()), - notifier(rs, *this) -{ - user->AddConnectedAfterNotifier(¬ifier); -} -//----------------------------------------------------------------------------- -RS::USER::USER(const RS::USER & rhs) - : lastSentTime(rhs.lastSentTime), - user(rhs.user), - routers(rhs.routers), - shortPacketsCount(rhs.shortPacketsCount), - ip(rhs.ip), - notifier(rhs.notifier) -{ - user->DelConnectedAfterNotifier(&rhs.notifier); - user->AddConnectedAfterNotifier(¬ifier); -} -//----------------------------------------------------------------------------- -RS::USER::~USER() -{ - user->DelConnectedAfterNotifier(¬ifier); -} -//----------------------------------------------------------------------------- RS::SETTINGS::SETTINGS() : sendPeriod(0), port(0), @@ -185,6 +170,7 @@ return 0; REMOTE_SCRIPT::REMOTE_SCRIPT() : ctx(), ipNotifierList(), + connNotifierList(), authorizedUsers(), errorStr(), rsSettings(), @@ -371,16 +357,16 @@ while (it != authorizedUsers.end()) { if (difftime(stgTime, it->second.lastSentTime) - (rand() % halfPeriod) > sendPeriod) { - Send(it->first, it->second); + Send(it->second); } ++it; } } //----------------------------------------------------------------------------- #ifdef NDEBUG -bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t, uint32_t ip, RS::USER & rsu, bool forceDisconnect) const +bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t, RS::USER & rsu, bool forceDisconnect) const #else -bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t bufSize, uint32_t ip, RS::USER & rsu, bool forceDisconnect) const +bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t bufSize, RS::USER & rsu, bool forceDisconnect) const #endif { RS::PACKET_HEADER packetHead; @@ -392,6 +378,7 @@ packetHead.protoVer[1] = '2'; if (forceDisconnect) { packetHead.packetType = RS_DISCONNECT_PACKET; + printfd(__FILE__, "RSCRIPT: force disconnect for '%s'\n", rsu.user->GetLogin().c_str()); } else { @@ -399,17 +386,25 @@ else { //SendLong packetHead.packetType = rsu.user->IsInetable() ? RS_CONNECT_PACKET : RS_DISCONNECT_PACKET; + if (rsu.user->IsInetable()) + printfd(__FILE__, "RSCRIPT: connect for '%s'\n", rsu.user->GetLogin().c_str()); + else + printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str()); } else { //SendShort packetHead.packetType = rsu.user->IsInetable() ? RS_ALIVE_PACKET : RS_DISCONNECT_PACKET; + if (rsu.user->IsInetable()) + printfd(__FILE__, "RSCRIPT: alive for '%s'\n", rsu.user->GetLogin().c_str()); + else + printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str()); } } rsu.shortPacketsCount++; rsu.lastSentTime = stgTime; -packetHead.ip = htonl(ip); +packetHead.ip = htonl(rsu.ip); packetHead.id = htonl(rsu.user->GetID()); strncpy((char*)packetHead.login, rsu.user->GetLogin().c_str(), RS_LOGIN_LEN); packetHead.login[RS_LOGIN_LEN - 1] = 0; @@ -446,13 +441,13 @@ Encrypt(&ctx, buf + sizeof(packetHead), (char *)&packetTail, sizeof(packetTail) return false; } //----------------------------------------------------------------------------- -bool REMOTE_SCRIPT::Send(uint32_t ip, RS::USER & rsu, bool forceDisconnect) const +bool REMOTE_SCRIPT::Send(RS::USER & rsu, bool forceDisconnect) const { char buffer[RS_MAX_PACKET_LEN]; memset(buffer, 0, sizeof(buffer)); -if (PreparePacket(buffer, sizeof(buffer), ip, rsu, forceDisconnect)) +if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect)) { printfd(__FILE__, "REMOTE_SCRIPT::Send() - Invalid packet length!\n"); return true; @@ -467,11 +462,11 @@ std::for_each( return false; } //----------------------------------------------------------------------------- -bool REMOTE_SCRIPT::SendDirect(uint32_t ip, RS::USER & rsu, uint32_t routerIP, bool forceDisconnect) const +bool REMOTE_SCRIPT::SendDirect(RS::USER & rsu, uint32_t routerIP, bool forceDisconnect) const { char buffer[RS_MAX_PACKET_LEN]; -if (PreparePacket(buffer, sizeof(buffer), ip, rsu, forceDisconnect)) +if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect)) { printfd(__FILE__, "REMOTE_SCRIPT::SendDirect() - Invalid packet length!\n"); return true; @@ -500,7 +495,7 @@ assert(h && "USERS::OpenSearch is always correct"); while (!users->SearchNext(h, &u)) { - SetUserNotifier(u); + SetUserNotifiers(u); } users->CloseSearch(h); @@ -516,8 +511,8 @@ void REMOTE_SCRIPT::ChangedIP(USER_PTR u, uint32_t oldIP, uint32_t newIP) */ if (newIP) { - RS::USER rsu(IP2Routers(newIP), u, *this); - Send(newIP, rsu); + RS::USER rsu(IP2Routers(newIP), u); + Send(rsu); STG_LOCKER lock(&mutex, __FILE__, __LINE__); authorizedUsers.insert(std::make_pair(newIP, rsu)); @@ -530,7 +525,7 @@ else ); if (it != authorizedUsers.end()) { - Send(oldIP, it->second, true); + Send(it->second, true); authorizedUsers.erase(it); } } @@ -629,44 +624,62 @@ else return value; } //----------------------------------------------------------------------------- -void REMOTE_SCRIPT::SetUserNotifier(USER_PTR u) +void REMOTE_SCRIPT::SetUserNotifiers(USER_PTR u) { ipNotifierList.push_front(RS::IP_NOTIFIER(*this, u)); - -u->AddCurrIPAfterNotifier(&(*ipNotifierList.begin())); +connNotifierList.push_front(RS::CONNECTED_NOTIFIER(*this, u)); } //----------------------------------------------------------------------------- -void REMOTE_SCRIPT::UnSetUserNotifier(USER_PTR u) +void REMOTE_SCRIPT::UnSetUserNotifiers(USER_PTR u) { -list::iterator ipAIter; -std::list::iterator> toErase; +ipNotifierList.erase(std::remove_if(ipNotifierList.begin(), + ipNotifierList.end(), + USER_IS(u)), + ipNotifierList.end()); +connNotifierList.erase(std::remove_if(connNotifierList.begin(), + connNotifierList.end(), + USER_IS(u)), + connNotifierList.end()); -for (ipAIter = ipNotifierList.begin(); ipAIter != ipNotifierList.end(); ++ipAIter) - { - if (ipAIter->GetUser() == u) - { - u->DelCurrIPAfterNotifier(&(*ipAIter)); - toErase.push_back(ipAIter); - } - } - -std::list::iterator>::iterator eIter; +} +//----------------------------------------------------------------------------- +void REMOTE_SCRIPT::AddRSU(USER_PTR user) +{ +RS::USER rsu(IP2Routers(user->GetCurrIP()), user); +Send(rsu); -for (eIter = toErase.begin(); eIter != toErase.end(); ++eIter) +STG_LOCKER lock(&mutex, __FILE__, __LINE__); +authorizedUsers.insert(std::make_pair(user->GetCurrIP(), rsu)); +} +//----------------------------------------------------------------------------- +void REMOTE_SCRIPT::DelRSU(USER_PTR user) +{ +STG_LOCKER lock(&mutex, __FILE__, __LINE__); +const map::iterator it( + authorizedUsers.find(user->GetCurrIP()) + ); +if (it != authorizedUsers.end()) { - ipNotifierList.erase(*eIter); + Send(it->second, true); + authorizedUsers.erase(it); } } //----------------------------------------------------------------------------- -void RS::IP_NOTIFIER::Notify(const uint32_t & oldValue, const uint32_t & newValue) +void RS::IP_NOTIFIER::Notify(const uint32_t & /*oldValue*/, const uint32_t & newValue) { -rs.ChangedIP(user, oldValue, newValue); +//rs.ChangedIP(user, oldValue, newValue); +if (newValue) + rs.AddRSU(user); +else + rs.DelRSU(user); } //----------------------------------------------------------------------------- void RS::CONNECTED_NOTIFIER::Notify(const bool & /*oldValue*/, const bool & newValue) { -if (!newValue) - rs.Send(user.ip, user, true); +if (newValue) + rs.AddRSU(user); +else + rs.DelRSU(user); } //----------------------------------------------------------------------------- void REMOTE_SCRIPT::InitEncrypt(BLOWFISH_CTX * ctx, const string & password) const diff --git a/projects/stargazer/plugins/other/rscript/rscript.h b/projects/stargazer/plugins/other/rscript/rscript.h index 001d65e1..e0118638 100644 --- a/projects/stargazer/plugins/other/rscript/rscript.h +++ b/projects/stargazer/plugins/other/rscript/rscript.h @@ -89,47 +89,65 @@ private: class IP_NOTIFIER: public PROPERTY_NOTIFIER_BASE { public: IP_NOTIFIER(REMOTE_SCRIPT & r, USER_PTR u) - : PROPERTY_NOTIFIER_BASE(), user(u), rs(r) {} + : PROPERTY_NOTIFIER_BASE(), user(u), rs(r) { user->AddCurrIPAfterNotifier(this); } IP_NOTIFIER(const IP_NOTIFIER & rhs) - : PROPERTY_NOTIFIER_BASE(), user(rhs.user), rs(rhs.rs) {} + : PROPERTY_NOTIFIER_BASE(), user(rhs.user), rs(rhs.rs) { user->AddCurrIPAfterNotifier(this); } + ~IP_NOTIFIER() { user->DelCurrIPAfterNotifier(this); } + + IP_NOTIFIER & operator=(const IP_NOTIFIER & rhs) + { + user->DelCurrIPAfterNotifier(this); + user = rhs.user; + user->AddCurrIPAfterNotifier(this); + return *this; + } + void Notify(const uint32_t & oldValue, const uint32_t & newValue); - USER_PTR GetUser() { return user; } + USER_PTR GetUser() const { return user; } private: - IP_NOTIFIER & operator=(const IP_NOTIFIER & rhs); USER_PTR user; REMOTE_SCRIPT & rs; }; //----------------------------------------------------------------------------- -class USER; -//----------------------------------------------------------------------------- class CONNECTED_NOTIFIER: public PROPERTY_NOTIFIER_BASE { public: - CONNECTED_NOTIFIER(REMOTE_SCRIPT & r, USER & u) - : PROPERTY_NOTIFIER_BASE(), user(u), rs(r) {} + CONNECTED_NOTIFIER(REMOTE_SCRIPT & r, USER_PTR u) + : PROPERTY_NOTIFIER_BASE(), user(u), rs(r) { user->AddConnectedAfterNotifier(this); } CONNECTED_NOTIFIER(const CONNECTED_NOTIFIER & rhs) - : PROPERTY_NOTIFIER_BASE(), user(rhs.user), rs(rhs.rs) {} + : PROPERTY_NOTIFIER_BASE(), user(rhs.user), rs(rhs.rs) { user->AddConnectedAfterNotifier(this); } + ~CONNECTED_NOTIFIER() { user->DelConnectedAfterNotifier(this); } + + CONNECTED_NOTIFIER & operator=(const CONNECTED_NOTIFIER & rhs) + { + user->DelConnectedAfterNotifier(this); + user = rhs.user; + user->AddConnectedAfterNotifier(this); + return *this; + } + void Notify(const bool & oldValue, const bool & newValue); + USER_PTR GetUser() const { return user; } private: - CONNECTED_NOTIFIER & operator=(const CONNECTED_NOTIFIER & rhs); - USER & user; + USER_PTR user; REMOTE_SCRIPT & rs; }; //----------------------------------------------------------------------------- struct USER { - USER(const std::vector & r, USER_PTR it, REMOTE_SCRIPT & rs); - USER(const USER & rhs); - ~USER(); + USER(const std::vector & r, USER_PTR it) + : user(it), + routers(r), + ip(user->GetCurrIP()) + {} time_t lastSentTime; USER_PTR user; std::vector routers; int shortPacketsCount; uint32_t ip; - CONNECTED_NOTIFIER notifier; }; //----------------------------------------------------------------------------- class SETTINGS { @@ -174,10 +192,12 @@ public: uint16_t GetStartPosition() const { return 10; } uint16_t GetStopPosition() const { return 10; } - void DelUser(USER_PTR u) { UnSetUserNotifier(u); } - void AddUser(USER_PTR u) { SetUserNotifier(u); } + void DelUser(USER_PTR u) { UnSetUserNotifiers(u); } + void AddUser(USER_PTR u) { SetUserNotifiers(u); } void ChangedIP(USER_PTR u, uint32_t oldIP, uint32_t newIP); + void AddRSU(USER_PTR user); + void DelRSU(USER_PTR user); private: REMOTE_SCRIPT(const REMOTE_SCRIPT & rhs); @@ -187,17 +207,17 @@ private: bool PrepareNet(); bool FinalizeNet(); - bool Send(uint32_t ip, USER & rsu, bool forceDisconnect = false) const; - bool SendDirect(uint32_t ip, USER & rsu, uint32_t routerIP, bool forceDisconnect = false) const; - bool PreparePacket(char * buf, size_t bufSize, uint32_t ip, USER &rsu, bool forceDisconnect = false) const; + bool Send(USER & rsu, bool forceDisconnect = false) const; + bool SendDirect(USER & rsu, uint32_t routerIP, bool forceDisconnect = false) const; + bool PreparePacket(char * buf, size_t bufSize, USER &rsu, bool forceDisconnect = false) const; void PeriodicSend(); std::vector IP2Routers(uint32_t ip); bool GetUsers(); std::string GetUserParam(USER_PTR u, const std::string & paramName) const; - void SetUserNotifier(USER_PTR u); - void UnSetUserNotifier(USER_PTR u); + void SetUserNotifiers(USER_PTR u); + void UnSetUserNotifiers(USER_PTR u); void InitEncrypt(BLOWFISH_CTX * ctx, const string & password) const; void Encrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, size_t len8) const; @@ -205,6 +225,7 @@ private: mutable BLOWFISH_CTX ctx; std::list ipNotifierList; + std::list connNotifierList; std::map authorizedUsers; mutable std::string errorStr; @@ -240,7 +261,7 @@ class DisconnectUser : public std::unary_function & p) { - rscript.Send(p.first, p.second, true); + rscript.Send(p.second, true); } private: REMOTE_SCRIPT & rscript; diff --git a/projects/stargazer/plugins/other/rscript/ur_functor.h b/projects/stargazer/plugins/other/rscript/ur_functor.h index c5752e87..5d02d9dc 100644 --- a/projects/stargazer/plugins/other/rscript/ur_functor.h +++ b/projects/stargazer/plugins/other/rscript/ur_functor.h @@ -41,7 +41,7 @@ public: void operator() (std::pair & val) { - std::vector newRouters = obj.IP2Routers(val.first); + std::vector newRouters = obj.IP2Routers(val.second.ip); std::vector::const_iterator oldIt(val.second.routers.begin()); std::vector::const_iterator newIt(newRouters.begin()); val.second.shortPacketsCount = 0; @@ -52,23 +52,23 @@ public: { if (newIt != newRouters.end()) { - obj.SendDirect(val.first, val.second, *newIt); // Connect on new router + obj.SendDirect(val.second, *newIt); // Connect on new router ++newIt; } } else if (newIt == newRouters.end()) { - obj.SendDirect(val.first, val.second, *oldIt, true); // Disconnect on old router + obj.SendDirect(val.second, *oldIt, true); // Disconnect on old router ++oldIt; } else if (*oldIt < *newIt) { - obj.SendDirect(val.first, val.second, *oldIt, true); // Disconnect on old router + obj.SendDirect(val.second, *oldIt, true); // Disconnect on old router ++oldIt; } else if (*oldIt > *newIt) { - obj.SendDirect(val.first, val.second, *newIt); // Connect on new router + obj.SendDirect(val.second, *newIt); // Connect on new router ++newIt; } else -- 2.43.2