]> git.stg.codes - stg.git/blobdiff - projects/stargazer/plugins/other/smux/smux.cpp
Fix tariff and user subscription in SMUX
[stg.git] / projects / stargazer / plugins / other / smux / smux.cpp
index f6c1fade56bc7b9b622e94a7570f7672284415b0..cc69aa8132f79bb9f96af718048ce519198b7fc9 100644 (file)
@@ -6,12 +6,22 @@
 #include <cerrno>
 #include <ctime>
 #include <csignal>
+#include <cassert>
 
 #include <vector>
 #include <algorithm>
+#include <iterator>
+#include <stdexcept>
+#include <utility>
 
 #include "stg/common.h"
 #include "stg/plugin_creator.h"
+/*#include "stg/users.h"
+#include "stg/tariffs.h"
+#include "stg/admins.h"
+#include "stg/services.h"
+#include "stg/corporations.h"
+#include "stg/traffcounter.h"*/
 
 #include "smux.h"
 #include "utils.h"
@@ -23,6 +33,12 @@ PLUGIN * GetPlugin()
 return smc.GetPlugin();
 }
 
+bool SPrefixLess(const Sensors::value_type & a,
+                 const Sensors::value_type & b)
+{
+return a.first.PrefixLess(b.first);
+}
+
 SMUX_SETTINGS::SMUX_SETTINGS()
     : ip(0),
       port(0)
@@ -80,9 +96,21 @@ SMUX::SMUX()
     : PLUGIN(),
       users(NULL),
       tariffs(NULL),
+      admins(NULL),
+      services(NULL),
+      corporations(NULL),
+      traffcounter(NULL),
       running(false),
       stopped(true),
-      sock(-1)
+      sock(-1),
+      smuxHandlers(),
+      pdusHandlers(),
+      sensors(),
+      tables(),
+      notifiers(),
+      addUserNotifier(*this),
+      delUserNotifier(*this),
+      addDelTariffNotifier(*this)
 {
 pthread_mutex_init(&mutex, NULL);
 
@@ -98,9 +126,16 @@ pdusHandlers[PDUs_PR_set_request] = &SMUX::SetRequestHandler;
 
 SMUX::~SMUX()
 {
-Sensors::iterator it;
-for (it = sensors.begin(); it != sensors.end(); ++it)
-    delete it->second;
+    {
+    Sensors::iterator it;
+    for (it = sensors.begin(); it != sensors.end(); ++it)
+        delete it->second;
+    }
+    {
+    Tables::iterator it;
+    for (it = tables.begin(); it != tables.end(); ++it)
+        delete it->second;
+    }
 printfd(__FILE__, "SMUX::~SMUX()\n");
 pthread_mutex_destroy(&mutex);
 }
@@ -112,6 +147,13 @@ return smuxSettings.ParseSettings(settings);
 
 int SMUX::Start()
 {
+assert(users != NULL && "users must not be NULL");
+assert(tariffs != NULL && "tariffs must not be NULL");
+assert(admins != NULL && "admins must not be NULL");
+assert(services != NULL && "services must not be NULL");
+assert(corporations != NULL && "corporations must not be NULL");
+assert(traffcounter != NULL && "traffcounter must not be NULL");
+
 if (PrepareNet())
     return -1;
 
@@ -129,6 +171,31 @@ sensors[OID(".1.3.6.1.4.1.38313.1.1.11")] = new FreeMbUsersSensor(*users);
 sensors[OID(".1.3.6.1.4.1.38313.1.1.12")] = new TariffChangeUsersSensor(*users);
 // Tariffs
 sensors[OID(".1.3.6.1.4.1.38313.1.2.1")] = new TotalTariffsSensor(*tariffs);
+// Admins
+sensors[OID(".1.3.6.1.4.1.38313.1.3.1")] = new TotalAdminsSensor(*admins);
+// Services
+sensors[OID(".1.3.6.1.4.1.38313.1.4.1")] = new TotalServicesSensor(*services);
+// Corporations
+sensors[OID(".1.3.6.1.4.1.38313.1.5.1")] = new TotalCorporationsSensor(*corporations);
+// Traffcounter
+sensors[OID(".1.3.6.1.4.1.38313.1.6.1")] = new TotalRulesSensor(*traffcounter);
+
+// Table data
+tables[".1.3.6.1.4.1.38313.1.1.6"] = new TariffUsersTable(".1.3.6.1.4.1.38313.1.1.6", *tariffs, *users);
+
+UpdateTables();
+SetNotifiers();
+
+#ifdef DEBUG
+Sensors::const_iterator it(sensors.begin());
+while (it != sensors.end())
+    {
+    printfd(__FILE__, "%s = %s\n",
+            it->first.ToString().c_str(),
+            it->second->ToString().c_str());
+    ++it;
+    }
+#endif
 
 if (!running)
     {
@@ -148,6 +215,8 @@ int SMUX::Stop()
 printfd(__FILE__, "SMUX::Stop() - Before\n");
 running = false;
 
+ResetNotifiers();
+
 if (!stopped)
     {
     //5 seconds to thread stops itself
@@ -194,13 +263,17 @@ SendOpenPDU(sock);
 SendRReqPDU(sock);
 running = true;
 stopped = false;
+
 while(running)
     {
     if (WaitPackets(sock))
         {
         SMUX_PDUs_t * pdus = RecvSMUXPDUs(sock);
         if (pdus)
+            {
             DispatchPDUs(pdus);
+            ASN_STRUCT_FREE(asn_DEF_SMUX_PDUs, pdus);
+            }
         }
     if (!running)
         break;
@@ -264,3 +337,118 @@ else
     }
 return false;
 }
+
+bool SMUX::UpdateTables()
+{
+Sensors newSensors;
+bool done = true;
+Tables::iterator it(tables.begin());
+while (it != tables.end())
+    {
+    try
+        {
+        it->second->UpdateSensors(newSensors);
+        }
+    catch (const std::runtime_error & ex)
+        {
+        printfd(__FILE__,
+                "SMUX::UpdateTables - failed to update table '%s': '%s'\n",
+                it->first.c_str(), ex.what());
+        done = false;
+        break;
+        }
+    ++it;
+    }
+if (!done)
+    {
+    Sensors::iterator it(newSensors.begin());
+    while (it != newSensors.end())
+        {
+        delete it->second;
+        ++it;
+        }
+    return false;
+    }
+
+it = tables.begin();
+while (it != tables.end())
+    {
+    std::pair<Sensors::iterator, Sensors::iterator> res;
+    res = std::equal_range(sensors.begin(),
+                           sensors.end(),
+                           std::pair<OID, Sensor *>(OID(it->first), NULL),
+                           SPrefixLess);
+    Sensors::iterator sit(res.first);
+    while (sit != res.second)
+        {
+        delete sit->second;
+        ++sit;
+        }
+    sensors.erase(res.first, res.second);
+    ++it;
+    }
+
+sensors.insert(newSensors.begin(), newSensors.end());
+
+return true;
+}
+
+void SMUX::SetNotifier(USER_PTR userPtr)
+{
+notifiers.push_back(CHG_AFTER_NOTIFIER(*this, userPtr));
+userPtr->GetProperty().tariffName.AddAfterNotifier(&notifiers.back());
+}
+
+void SMUX::UnsetNotifier(USER_PTR userPtr)
+{
+std::list<CHG_AFTER_NOTIFIER>::iterator it = notifiers.begin();
+while (it != notifiers.end())
+    {
+    if (it->GetUserPtr() == userPtr)
+        {
+        userPtr->GetProperty().tariffName.DelAfterNotifier(&(*it));
+        notifiers.erase(it);
+        break;
+        }
+    ++it;
+    }
+}
+
+void SMUX::SetNotifiers()
+{
+int h = users->OpenSearch();
+assert(h && "USERS::OpenSearch is always correct");
+
+USER_PTR u;
+while (!users->SearchNext(h, &u))
+    SetNotifier(u);
+
+users->CloseSearch(h);
+
+users->AddNotifierUserAdd(&addUserNotifier);
+users->AddNotifierUserDel(&delUserNotifier);
+
+tariffs->AddNotifierAdd(&addDelTariffNotifier);
+tariffs->AddNotifierDel(&addDelTariffNotifier);
+}
+
+void SMUX::ResetNotifiers()
+{
+tariffs->DelNotifierDel(&addDelTariffNotifier);
+tariffs->DelNotifierAdd(&addDelTariffNotifier);
+
+users->DelNotifierUserDel(&delUserNotifier);
+users->DelNotifierUserAdd(&addUserNotifier);
+
+std::list<CHG_AFTER_NOTIFIER>::iterator it = notifiers.begin();
+while (it != notifiers.end())
+    {
+    it->GetUserPtr()->GetProperty().tariffName.DelAfterNotifier(&(*it));
+    ++it;
+    }
+}
+
+void CHG_AFTER_NOTIFIER::Notify(const std::string &, const std::string &)
+{
+smux.UpdateTables();
+}