--- /dev/null
+[submodule "3rdparty/jthread"]
+       path = 3rdparty/jthread
+       url = https://github.com/josuttis/jthread.git
 
--- /dev/null
+Subproject commit 0fa8d394254886c555d6faccd0a3de819b7d47f8
 
 
 set ( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules )
 
-if ( CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.5 )
-    message ( FATAL_ERROR "Require at least gcc-6.5" )
-endif( CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.5 )
-
 option ( BUILD_STG "Build Stargazer server." OFF )
 option ( BUILD_SGCONF "Build SGConf client." OFF )
 option ( BUILD_RSCRIPTD "Build RScriptD server." OFF )
 endif ( BUILD_MOD_SMUX OR BUILD_ALL_LIBS )
 
 enable_language (CXX)
-set (CMAKE_CXX_STANDARD 14)
+set (CMAKE_CXX_STANDARD 17)
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -Wextra -Wshadow -Wno-long-long -Wold-style-cast -Wstrict-aliasing -pedantic")
 
 if ( CMAKE_COMPILER_IS_GNUCC )
 endif ()
 
 include_directories ( include )
+include_directories ( 3rdparty/jthread/source )
 
 add_subdirectory ( libs )
 add_subdirectory ( projects )
 
 if ( BUILD_TESTS )
+    enable_testing ()
     add_subdirectory ( tests )
 endif ( BUILD_TESTS )
 
     target_link_libraries ( ia crypto common )
 endif ( BUILD_LIB_IA )
 
-if ( BUILD_LIB_IBPP )
-    add_library ( ibpp STATIC ibpp/all_in_one.cpp )
-    target_include_directories ( ibpp PUBLIC ibpp/include )
-    target_compile_options ( ibpp PRIVATE -Wno-old-style-cast $<$<CXX_COMPILER_ID:GNU>:-Wno-useless-cast> )
-endif ( BUILD_LIB_IBPP )
+#if ( BUILD_LIB_IBPP )
+#    add_library ( ibpp STATIC ibpp/all_in_one.cpp )
+#    target_include_directories ( ibpp PUBLIC ibpp/include )
+#    target_compile_options ( ibpp PRIVATE -Wno-old-style-cast $<$<CXX_COMPILER_ID:GNU>:-Wno-useless-cast> )
+#endif ( BUILD_LIB_IBPP )
 
 if ( BUILD_LIB_LOGGER )
     add_library ( logger STATIC logger/logger.cpp )
 
     add_subdirectory ( stargazer )
 endif ( BUILD_STG )
 
-add_custom_target (cppcheck COMMAND cppcheck --enable=all --std=c++14 ${CMAKE_SOURCE_DIR}/rscriptd ${CMAKE_SOURCE_DIR}/sgauth ${CMAKE_SOURCE_DIR}/sgconf ${CMAKE_SOURCE_DIR}/stargazer)
+add_custom_target (cppcheck COMMAND /usr/bin/cppcheck --enable=all --std=c++14 ${CMAKE_SOURCE_DIR}/libs ${CMAKE_SOURCE_DIR}/projects/rscriptd ${CMAKE_SOURCE_DIR}/projects/sgauth ${CMAKE_SOURCE_DIR}/projects/sgconf ${CMAKE_SOURCE_DIR}/projects/stargazer)
 
                 plugin_mgr.cpp
                 settings_impl.cpp
                 stg_timer.cpp
-                timer_impl.cpp
                 store_loader.cpp
                 traffcounter_impl.cpp
                 user_property.cpp )
 
 //
 // actionsList.InvokeAll();
 
-#include <pthread.h>
 #include <vector>
 #include <functional>
+#include <mutex>
 
 // Generalized actor type - a method of some class with one argument
 template <class ACTIVE_CLASS, typename DATA_TYPE>
            typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
            DATA_TYPE d)
         : activeClass(ac), actor(a), data(d) {}
-    void Invoke();
+    void Invoke() override;
 private:
     ACTION(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
     ACTION<ACTIVE_CLASS, DATA_TYPE> & operator=(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue);
     // Invoke all actions in the list
     void InvokeAll();
 private:
-    mutable pthread_mutex_t mutex;
+    mutable std::mutex m_mutex;
 };
 
 #include "actions.inl.h"
 
 
 inline
 ACTIONS_LIST::ACTIONS_LIST()
-    : mutex()
 {
-pthread_mutex_init(&mutex, NULL);
 }
 
 // Delete all actions before deleting list
 inline
 ACTIONS_LIST::~ACTIONS_LIST()
 {
+std::lock_guard lock(m_mutex);
 
-    {
-    STG_LOCKER lock(&mutex);
-
-    parent::iterator it(parent::begin());
-    while (it != parent::end())
-        {
-        delete *it++;
-        }
-    }
-
-pthread_mutex_destroy(&mutex);
+parent::iterator it(parent::begin());
+while (it != parent::end())
+    delete *it++;
 }
 
 inline
 ACTIONS_LIST::parent::iterator ACTIONS_LIST::begin()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 return parent::begin();
 }
 
 inline
 ACTIONS_LIST::parent::iterator ACTIONS_LIST::end()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 return parent::end();
 }
 
 inline
 ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::begin() const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 return parent::begin();
 }
 
 inline
 ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::end() const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 return parent::end();
 }
 
 inline
 bool ACTIONS_LIST::empty() const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 return parent::empty();
 }
 
 inline
 size_t ACTIONS_LIST::size() const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 return parent::size();
 }
 
 inline
 void ACTIONS_LIST::swap(ACTIONS_LIST & list)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 parent::swap(list);
 }
 
                            typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a,
                            DATA_TYPE d)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 push_back(new ACTION<ACTIVE_CLASS, DATA_TYPE>(ac, a, d));
 }
 
 inline
 void ACTIONS_LIST::InvokeAll()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 std::for_each(
         parent::begin(),
         parent::end(),
 
 
     AdminsImpl admins(store);
     TariffsImpl tariffs(&store);
+    tariffs.ReadTariffs();
     ServicesImpl services(&store);
     CorporationsImpl corps(&store);
     UsersImpl users(&settings, &store, &tariffs, services, admins.sysAdmin());
 
     set_target_properties ( mod_store_files PROPERTIES PREFIX "" )
 endif ( BUILD_MOD_STORE_FILES )
 
-if ( BUILD_MOD_STORE_FIREBIRD )
-    find_package ( FBClient REQUIRED )
-    add_library ( mod_store_firebird MODULE store/firebird/firebird_store.cpp
-                                            store/firebird/firebird_store_admins.cpp
-                                            store/firebird/firebird_store_corporations.cpp
-                                            store/firebird/firebird_store_messages.cpp
-                                            store/firebird/firebird_store_services.cpp
-                                            store/firebird/firebird_store_tariffs.cpp
-                                            store/firebird/firebird_store_users.cpp
-                                            store/firebird/firebird_store_utils.cpp )
-    target_link_libraries ( mod_store_firebird crypto common logger ibpp FBClient::FBClient )
-    set_target_properties ( mod_store_firebird PROPERTIES PREFIX "" )
-endif ( BUILD_MOD_STORE_FIREBIRD )
+#if ( BUILD_MOD_STORE_FIREBIRD )
+#    find_package ( FBClient REQUIRED )
+#    add_library ( mod_store_firebird MODULE store/firebird/firebird_store.cpp
+#                                            store/firebird/firebird_store_admins.cpp
+#                                            store/firebird/firebird_store_corporations.cpp
+#                                            store/firebird/firebird_store_messages.cpp
+#                                            store/firebird/firebird_store_services.cpp
+#                                            store/firebird/firebird_store_tariffs.cpp
+#                                            store/firebird/firebird_store_users.cpp
+#                                            store/firebird/firebird_store_utils.cpp )
+#    target_link_libraries ( mod_store_firebird crypto common logger ibpp FBClient::FBClient )
+#    set_target_properties ( mod_store_firebird PROPERTIES PREFIX "" )
+#endif ( BUILD_MOD_STORE_FIREBIRD )
 
 if ( BUILD_MOD_STORE_MYSQL )
     find_package ( MySQLConnector REQUIRED )
 
       m_store(NULL),
       m_port(0),
       m_bindAddress("0.0.0.0"),
-      m_running(false),
       m_stopped(true),
       m_logger(l),
       m_listenSocket(-1)
 
     RegisterParsers();
 
-    m_running = true;
     m_stopped = false;
     return 0;
 }
 
 int CONFIGPROTO::Stop()
 {
-    m_running = false;
     for (int i = 0; i < 5 && !m_stopped; ++i)
     {
         struct timespec ts = {0, 200000000};
     return 0;
 }
 
-void CONFIGPROTO::Run()
+void CONFIGPROTO::Run(std::stop_token token)
 {
-    while (m_running)
+    while (!token.stop_requested())
     {
         fd_set fds;
 
             m_logger(m_errorStr);
             break;
         }
-        if (!m_running)
+        if (token.stop_requested())
             break;
         if (res > 0)
             HandleEvents(fds);
 
 
 #include <string>
 #include <deque>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
 #include <cstdint>
 
 #include <sys/select.h>
     int Prepare();
     int Stop();
     const std::string & GetStrError() const { return m_errorStr; }
-    void Run();
+    void Run(std::stop_token token);
 
 private:
     CONFIGPROTO(const CONFIGPROTO & rvalue);
 
     uint16_t         m_port;
     std::string      m_bindAddress;
-    bool             m_running;
     bool             m_stopped;
     STG::PluginLogger &   m_logger;
     int              m_listenSocket;
 
         printfd(__FILE__, "XML parse error at line %d, %d: %s. Is final: %d\n",
                   static_cast<int>(XML_GetCurrentLineNumber(state.conn.m_xmlParser)),
                   static_cast<int>(XML_GetCurrentColumnNumber(state.conn.m_xmlParser)),
-                  XML_ErrorString(XML_GetErrorCode(state.conn.m_xmlParser)), (int)state.final);
+                  XML_ErrorString(XML_GetErrorCode(state.conn.m_xmlParser)), static_cast<int>(state.final));
         printfd(__FILE__, "Data block: '%s' of size %d\n", xml, length);
         state.conn.m_state = ERROR;
         return false;
 
         ~Conn();
 
         int Sock() const { return m_sock; }
-        uint32_t IP() const { return *(uint32_t *)(&m_addr.sin_addr); }
+        uint32_t IP() const { return *reinterpret_cast<const uint32_t *>(&m_addr.sin_addr); }
         uint16_t Port() const { return ntohs(m_addr.sin_port); }
 
         std::string endpoint() const { return inet_ntostring(IP()) + ":" + std::to_string(Port()); }
 
         {
             public:
                 explicit FACTORY(const Admins & admins) : m_admins(admins) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_ADMINS(admin, m_admins); }
+                BASE_PARSER * create(const Admin & admin) override { return new GET_ADMINS(admin, m_admins); }
                 static void Register(REGISTRY & registry, const Admins & admins)
                 { registry[ToLower(tag)] = new FACTORY(admins); }
             private:
     private:
         const Admins & m_admins;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class ADD_ADMIN: public BASE_PARSER
         {
             public:
                 explicit FACTORY(Admins & admins) : m_admins(admins) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_ADMIN(admin, m_admins); }
+                BASE_PARSER * create(const Admin & admin) override { return new ADD_ADMIN(admin, m_admins); }
                 static void Register(REGISTRY & registry, Admins & admins)
                 { registry[ToLower(tag)] = new FACTORY(admins); }
             private:
 
         ADD_ADMIN(const Admin & admin, Admins & admins)
             : BASE_PARSER(admin, tag), m_admins(admins) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         std::string m_admin;
         Admins & m_admins;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class DEL_ADMIN: public BASE_PARSER
         {
             public:
                 explicit FACTORY(Admins & admins) : m_admins(admins) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_ADMIN(admin, m_admins); }
+                BASE_PARSER * create(const Admin & admin) override { return new DEL_ADMIN(admin, m_admins); }
                 static void Register(REGISTRY & registry, Admins & admins)
                 { registry[ToLower(tag)] = new FACTORY(admins); }
             private:
 
         DEL_ADMIN(const Admin & admin, Admins & admins)
             : BASE_PARSER(admin, tag), m_admins(admins) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         std::string m_admin;
         Admins & m_admins;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class CHG_ADMIN: public BASE_PARSER
         {
             public:
                 explicit FACTORY(Admins & admins) : m_admins(admins) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_ADMIN(admin, m_admins); }
+                BASE_PARSER * create(const Admin & admin) override { return new CHG_ADMIN(admin, m_admins); }
                 static void Register(REGISTRY & registry, Admins & admins)
                 { registry[ToLower(tag)] = new FACTORY(admins); }
             private:
 
         CHG_ADMIN(const Admin & admin, Admins & admins)
             : BASE_PARSER(admin, tag), m_admins(admins) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         std::string login;
         Optional<std::string> privAsString;
         Admins & m_admins;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 } // namespace PARSER
 
         {
             public:
                 explicit FACTORY(const Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new AUTH_BY(admin, m_users); }
+                BASE_PARSER * create(const Admin & admin) override { return new AUTH_BY(admin, m_users); }
                 static void Register(REGISTRY & registry, const Users & users)
                 { registry[ToLower(tag)] = new FACTORY(users); }
             private:
 
         AUTH_BY(const Admin & admin, const Users & users)
             : BASE_PARSER(admin, tag), m_users(users) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         const Users & m_users;
         std::string m_login;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 } // namespace PARSER
 
         {
             public:
                 explicit FACTORY(Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new SEND_MESSAGE(admin, m_users); }
+                BASE_PARSER * create(const Admin & admin) override { return new SEND_MESSAGE(admin, m_users); }
                 static void Register(REGISTRY & registry, Users & users)
                 { registry[ToLower(tag)] = new FACTORY(users); }
             private:
 
         SEND_MESSAGE(const Admin & admin, Users & users)
             : BASE_PARSER(admin, tag), m_users(users), m_result(res_ok), m_user(NULL) {}
-        int Start(void *data, const char *el, const char **attr);
-        int End(void *data, const char *el);
+        int Start(void *data, const char *el, const char **attr) override;
+        int End(void *data, const char *el) override;
 
     private:
         Users & m_users;
         User * m_user;
 
         int ParseLogins(const char * logins);
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 } // namespace PARSER
 
             public:
                 FACTORY(const Settings & settings, const Users & users, const Tariffs & tariffs)
                     : m_settings(settings), m_users(users), m_tariffs(tariffs) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_SERVER_INFO(admin, m_settings, m_users, m_tariffs); }
+                BASE_PARSER * create(const Admin & admin) override { return new GET_SERVER_INFO(admin, m_settings, m_users, m_tariffs); }
                 static void Register(REGISTRY & registry, const Settings & settings, const Users & users, const Tariffs & tariffs)
                 { registry[ToLower(tag)] = new FACTORY(settings, users, tariffs); }
             private:
         const Users & m_users;
         const Tariffs & m_tariffs;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 }
 
         class FACTORY : public BASE_PARSER::FACTORY
         {
             public:
-                FACTORY(const Services & services) : m_services(services) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_SERVICES(admin, m_services); }
+                explicit FACTORY(const Services & services) : m_services(services) {}
+                BASE_PARSER * create(const Admin & admin) override { return new GET_SERVICES(admin, m_services); }
                 static void Register(REGISTRY & registry, const Services & services)
                 { registry[ToLower(tag)] = new FACTORY(services); }
             private:
     private:
         const Services & m_services;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class GET_SERVICE: public BASE_PARSER
         class FACTORY : public BASE_PARSER::FACTORY
         {
             public:
-                FACTORY(const Services & services) : m_services(services) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_SERVICE(admin, m_services); }
+                explicit FACTORY(const Services & services) : m_services(services) {}
+                BASE_PARSER * create(const Admin & admin) override { return new GET_SERVICE(admin, m_services); }
                 static void Register(REGISTRY & registry, Services & services)
                 { registry[ToLower(tag)] = new FACTORY(services); }
             private:
 
         GET_SERVICE(const Admin & admin, const Services & services)
             : BASE_PARSER(admin, tag), m_services(services) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         std::string m_name;
         const Services & m_services;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class ADD_SERVICE: public BASE_PARSER
         class FACTORY : public BASE_PARSER::FACTORY
         {
             public:
-                FACTORY(Services & services) : m_services(services) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_SERVICE(admin, m_services); }
+                explicit FACTORY(Services & services) : m_services(services) {}
+                BASE_PARSER * create(const Admin & admin) override { return new ADD_SERVICE(admin, m_services); }
                 static void Register(REGISTRY & registry, Services & services)
                 { registry[ToLower(tag)] = new FACTORY(services); }
             private:
 
         ADD_SERVICE(const Admin & admin, Services & services)
             : BASE_PARSER(admin, tag), m_services(services) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         std::string m_name;
         Services & m_services;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class DEL_SERVICE: public BASE_PARSER
         class FACTORY : public BASE_PARSER::FACTORY
         {
             public:
-                FACTORY(Services & services) : m_services(services) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_SERVICE(admin, m_services); }
+                explicit FACTORY(Services & services) : m_services(services) {}
+                BASE_PARSER * create(const Admin & admin) override { return new DEL_SERVICE(admin, m_services); }
                 static void Register(REGISTRY & registry, Services & services)
                 { registry[ToLower(tag)] = new FACTORY(services); }
             private:
 
         DEL_SERVICE(const Admin & admin, Services & services)
             : BASE_PARSER(admin, tag), m_services(services) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         std::string m_name;
         Services & m_services;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class CHG_SERVICE: public BASE_PARSER
         class FACTORY : public BASE_PARSER::FACTORY
         {
             public:
-                FACTORY(Services & services) : m_services(services) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_SERVICE(admin, m_services); }
+                explicit FACTORY(Services & services) : m_services(services) {}
+                BASE_PARSER * create(const Admin & admin) override { return new CHG_SERVICE(admin, m_services); }
                 static void Register(REGISTRY & registry, Services & services)
                 { registry[ToLower(tag)] = new FACTORY(services); }
             private:
 
         CHG_SERVICE(const Admin & admin, Services & services)
             : BASE_PARSER(admin, tag), m_services(services) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         ServiceConfOpt m_service;
         Services & m_services;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 } // namespace PARSER
 
         {
             int64_t policyTime = 0;
             if (str2x(attr[1], policyTime) == 0)
-                td.tariffConf.changePolicyTimeout = (time_t)policyTime;
+                td.tariffConf.changePolicyTimeout = policyTime;
             return 0;
         }
     }
 
         {
             public:
                 explicit FACTORY(const Tariffs & tariffs) : m_tariffs(tariffs) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_TARIFFS(admin, m_tariffs); }
+                BASE_PARSER * create(const Admin & admin) override { return new GET_TARIFFS(admin, m_tariffs); }
                 static void Register(REGISTRY & registry, const Tariffs & tariffs)
                 { registry[ToLower(tag)] = new FACTORY(tariffs); }
             private:
     private:
         const Tariffs & m_tariffs;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class ADD_TARIFF: public BASE_PARSER
         {
             public:
                 explicit FACTORY(Tariffs & tariffs) : m_tariffs(tariffs) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_TARIFF(admin, m_tariffs); }
+                BASE_PARSER * create(const Admin & admin) override { return new ADD_TARIFF(admin, m_tariffs); }
                 static void Register(REGISTRY & registry, Tariffs & tariffs)
                 { registry[ToLower(tag)] = new FACTORY(tariffs); }
             private:
 
         ADD_TARIFF(const Admin & admin, Tariffs & tariffs)
             : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         std::string tariff;
         Tariffs & m_tariffs;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class DEL_TARIFF: public BASE_PARSER
         {
             public:
                 FACTORY(Tariffs & tariffs, const Users & users) : m_tariffs(tariffs), m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_TARIFF(admin, m_users, m_tariffs); }
+                BASE_PARSER * create(const Admin & admin) override { return new DEL_TARIFF(admin, m_users, m_tariffs); }
                 static void Register(REGISTRY & registry, Tariffs & tariffs, const Users & users)
                 { registry[ToLower(tag)] = new FACTORY(tariffs, users); }
             private:
 
         DEL_TARIFF(const Admin & admin, const Users & users, Tariffs & tariffs)
             : BASE_PARSER(admin, tag), m_users(users), m_tariffs(tariffs) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         std::string tariff;
         const Users & m_users;
         Tariffs & m_tariffs;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class CHG_TARIFF: public BASE_PARSER
         {
             public:
                 explicit FACTORY(Tariffs & tariffs) : m_tariffs(tariffs) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_TARIFF(admin, m_tariffs); }
+                BASE_PARSER * create(const Admin & admin) override { return new CHG_TARIFF(admin, m_tariffs); }
                 static void Register(REGISTRY & registry, Tariffs & tariffs)
                 { registry[ToLower(tag)] = new FACTORY(tariffs); }
             private:
 
         CHG_TARIFF(const Admin & admin, Tariffs & tariffs)
             : BASE_PARSER(admin, tag), m_tariffs(tariffs) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         TariffDataOpt td;
         Tariffs & m_tariffs;
 
         int CheckTariffData();
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 } // namespace PARSER
 
         class FACTORY : public BASE_PARSER::FACTORY
         {
             public:
-                FACTORY(const Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new USER_INFO(admin, m_users); }
+                explicit FACTORY(const Users & users) : m_users(users) {}
+                BASE_PARSER * create(const Admin & admin) override { return new USER_INFO(admin, m_users); }
                 static void Register(REGISTRY & registry, const Users & users)
                 { registry[ToLower(tag)] = new FACTORY(users); }
             private:
 
         USER_INFO(const Admin & admin, const Users & users)
             : BASE_PARSER(admin, tag), m_users(users) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         const Users & m_users;
         std::string m_login;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 } // namespace PARSER
 
         {
             long int creditExpire = 0;
             if (str2x(attr[1], creditExpire) == 0)
-                m_ucr.creditExpire = (time_t)creditExpire;
+                m_ucr.creditExpire = creditExpire;
 
             return 0;
         }
     userdata.push_back(u->GetProperties().userdata8.GetPointer());
     userdata.push_back(u->GetProperties().userdata9.GetPointer());
 
-    for (int i = 0; i < (int)userdata.size(); i++)
+    for (size_t i = 0; i < userdata.size(); i++)
         if (!m_ucr.userdata[i].empty())
             if(!userdata[i]->Set(m_ucr.userdata[i].const_data(), m_currAdmin, m_login, m_store))
                 return -1;
 
         {
             public:
                 explicit FACTORY(Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_USERS(admin, m_users); }
+                BASE_PARSER * create(const Admin & admin) override { return new GET_USERS(admin, m_users); }
                 static void Register(REGISTRY & registry, Users & users)
                 { registry[ToLower(tag)] = new FACTORY(users); }
             private:
         GET_USERS(const Admin & admin, Users & users)
             : BASE_PARSER(admin, tag), m_users(users),
               m_lastUserUpdateTime(0) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         Users & m_users;
         time_t m_lastUserUpdateTime;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class GET_USER: public BASE_PARSER
         {
             public:
                 explicit FACTORY(const Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new GET_USER(admin, m_users); }
+                BASE_PARSER * create(const Admin & admin) override { return new GET_USER(admin, m_users); }
                 static void Register(REGISTRY & registry, const Users & users)
                 { registry[ToLower(tag)] = new FACTORY(users); }
             private:
 
         GET_USER(const Admin & admin, const Users & users)
             : BASE_PARSER(admin, tag), m_users(users) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         const Users & m_users;
         std::string m_login;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class ADD_USER: public BASE_PARSER
         {
             public:
                 explicit FACTORY(Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new ADD_USER(admin, m_users); }
+                BASE_PARSER * create(const Admin & admin) override { return new ADD_USER(admin, m_users); }
                 static void Register(REGISTRY & registry, Users & users)
                 { registry[ToLower(tag)] = new FACTORY(users); }
             private:
 
         ADD_USER(const Admin & admin, Users & users)
             : BASE_PARSER(admin, tag), m_users(users) {}
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         Users & m_users;
         std::string m_login;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class CHG_USER: public BASE_PARSER
                 FACTORY(Users & users, Store & store, const Tariffs & tariffs)
                     : m_users(users), m_store(store), m_tariffs(tariffs)
                 {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new CHG_USER(admin, m_users, m_store, m_tariffs); }
+                BASE_PARSER * create(const Admin & admin) override { return new CHG_USER(admin, m_users, m_store, m_tariffs); }
                 static void Register(REGISTRY & registry, Users & users, Store & store, const Tariffs & tariffs)
                 { registry[ToLower(tag)] = new FACTORY(users, store, tariffs); }
             private:
               m_tariffs(tariffs),
               m_cashMustBeAdded(false) {}
 
-        int Start(void * data, const char * el, const char ** attr);
+        int Start(void * data, const char * el, const char ** attr) override;
 
     private:
         Users & m_users;
         bool m_cashMustBeAdded;
 
         int ApplyChanges();
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class DEL_USER: public BASE_PARSER
         {
             public:
                 explicit FACTORY(Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new DEL_USER(admin, m_users); }
+                BASE_PARSER * create(const Admin & admin) override { return new DEL_USER(admin, m_users); }
                 static void Register(REGISTRY & registry, Users & users)
                 { registry[ToLower(tag)] = new FACTORY(users); }
             private:
 
         DEL_USER(const Admin & admin, Users & users)
             : BASE_PARSER(admin, tag), m_users(users), res(0), u(NULL) {}
-        int Start(void * data, const char * el, const char ** attr);
-        int End(void * data, const char * el);
+        int Start(void * data, const char * el, const char ** attr) override;
+        int End(void * data, const char * el) override;
 
     private:
         Users & m_users;
         int res;
         User * u;
 
-        void CreateAnswer();
+        void CreateAnswer() override;
 };
 
 class CHECK_USER: public BASE_PARSER
         {
             public:
                 explicit FACTORY(const Users & users) : m_users(users) {}
-                virtual BASE_PARSER * create(const Admin & admin) { return new CHECK_USER(admin, m_users); }
+                BASE_PARSER * create(const Admin & admin) override { return new CHECK_USER(admin, m_users); }
                 static void Register(REGISTRY & registry, const Users & users)
                 { registry[ToLower(tag)] = new FACTORY(users); }
             private:
 
         CHECK_USER(const Admin & admin, const Users & users)
             : BASE_PARSER(admin, tag), m_users(users) {}
-        int Start(void * data, const char * el, const char ** attr);
-        int End(void * data, const char * el);
+        int Start(void * data, const char * el, const char ** attr) override;
+        int End(void * data, const char * el) override;
 
     private:
         const Users & m_users;
 
         void CreateAnswer(const char * error);
-        void CreateAnswer() {} // dummy
+        void CreateAnswer() override {} // dummy
 };
 
 } // namespace PARSER
 
         return -1;
     }
 
-    if (pthread_create(&thread, NULL, Run, this))
-    {
-        errorStr = std::string("Cannot create thread: '") + strerror(errno) + "'.";
-        printfd(__FILE__, "%s\n", errorStr.c_str());
-        logger(errorStr);
-        return -1;
-    }
+    m_thread = std::jthread([this](auto token){ Run(token); });
 
     return 0;
 }
         return 0;
 
     config.Stop();
+    m_thread.request_stop();
 
     //5 seconds to thread stops itself
     for (size_t i = 0; i < 25; ++i)
     }
 
     if (isRunning)
-        return -1;
+        m_thread.detach();
 
     return 0;
 }
 //-----------------------------------------------------------------------------
-void * STG_CONFIG::Run(void * d)
+void STG_CONFIG::Run(std::stop_token token)
 {
     sigset_t signalSet;
     sigfillset(&signalSet);
     pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
 
-    STG_CONFIG & stgConf = *static_cast<STG_CONFIG *>(d);
-    stgConf.isRunning = true;
-
-    stgConf.config.Run();
+    isRunning = true;
 
-    stgConf.isRunning = false;
+    config.Run(token);
 
-    return NULL;
+    isRunning = false;
 }
 
 #include "stg/logger.h"
 
 #include <string>
-
-#include <pthread.h>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
 
 class STG_CONFIG_SETTINGS
 {
         STG_CONFIG(const STG_CONFIG & rvalue);
         STG_CONFIG & operator=(const STG_CONFIG & rvalue);
 
-        static void *       Run(void *);
+        void                Run(std::stop_token token);
 
         mutable std::string errorStr;
         STG_CONFIG_SETTINGS stgConfigSettings;
-        pthread_t           thread;
+        std::jthread        m_thread;
         bool                nonstop;
         bool                isRunning;
         STG::PluginLogger   logger;
 
 //-----------------------------------------------------------------------------
 PING::PING()
     : users(NULL),
-      nonstop(false),
       isRunning(false),
       onAddUserNotifier(*this),
       onDelUserNotifier(*this),
       logger(STG::PluginLogger::get("ping"))
 {
-pthread_mutex_init(&mutex, NULL);
 }
 //-----------------------------------------------------------------------------
 PING::~PING()
 {
-pthread_mutex_destroy(&mutex);
 }
 //-----------------------------------------------------------------------------
 int PING::ParseSettings()
 users->AddNotifierUserAdd(&onAddUserNotifier);
 users->AddNotifierUserDel(&onDelUserNotifier);
 
-nonstop = true;
-
 pinger.SetDelayTime(pingSettings.GetPingDelay());
 pinger.Start();
 
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    errorStr = "Cannot start thread.";
-    logger("Cannot create thread.");
-    printfd(__FILE__, "Cannot start thread\n");
-    return -1;
-    }
+m_thread = std::jthread([this](auto token){ Run(token); });
 
 return 0;
 }
 //-----------------------------------------------------------------------------
 int PING::Stop()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 
-if (!isRunning)
+if (!m_thread.joinable())
     return 0;
 
 pinger.Stop();
-nonstop = false;
+m_thread.request_stop();
 //5 seconds to thread stops itself
 struct timespec ts = {0, 200000000};
 for (int i = 0; i < 25; i++)
     }
 
 if (isRunning)
-    return -1;
+    m_thread.detach();
 
 return 0;
 }
 return isRunning;
 }
 //-----------------------------------------------------------------------------
-void * PING::Run(void * d)
+void PING::Run(std::stop_token token)
 {
 sigset_t signalSet;
 sigfillset(&signalSet);
 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
 
-PING * ping = static_cast<PING *>(d);
-ping->isRunning = true;
+isRunning = true;
 
-long delay = (10000000 * ping->pingSettings.GetPingDelay()) / 3 + 50000000;
+long delay = (10000000 * pingSettings.GetPingDelay()) / 3 + 50000000;
 
-while (ping->nonstop)
+while (!token.stop_requested())
     {
-    std::list<UserPtr>::iterator iter = ping->usersList.begin();
+    std::list<UserPtr>::iterator iter = usersList.begin();
         {
-        STG_LOCKER lock(&ping->mutex);
-        while (iter != ping->usersList.end())
+        std::lock_guard lock(m_mutex);
+        while (iter != usersList.end())
             {
             if ((*iter)->GetProperties().ips.ConstData().onlyOneIP())
                 {
                 uint32_t ip = (*iter)->GetProperties().ips.ConstData()[0].ip;
                 time_t t;
-                if (ping->pinger.GetIPTime(ip, &t) == 0)
+                if (pinger.GetIPTime(ip, &t) == 0)
                     {
                     if (t)
                         (*iter)->UpdatePingTime(t);
                 if (ip)
                     {
                     time_t t;
-                    if (ping->pinger.GetIPTime(ip, &t) == 0)
+                    if (pinger.GetIPTime(ip, &t) == 0)
                         {
                         if (t)
                             (*iter)->UpdatePingTime(t);
     struct timespec ts = {delay / 1000000000, delay % 1000000000};
     for (int i = 0; i < 100; i++)
         {
-        if (ping->nonstop)
+        if (!token.stop_requested())
             {
             nanosleep(&ts, NULL);
             }
         }
     }
 
-ping->isRunning = false;
-return NULL;
+isRunning = false;
 }
 //-----------------------------------------------------------------------------
 void PING::SetUserNotifiers(UserPtr u)
 //-----------------------------------------------------------------------------
 void PING::GetUsers()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 
 UserPtr u;
 int h = users->OpenSearch();
 //-----------------------------------------------------------------------------
 void PING::AddUser(UserPtr u)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 
 SetUserNotifiers(u);
 usersList.push_back(u);
 //-----------------------------------------------------------------------------
 void PING::DelUser(UserPtr u)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 
 UnSetUserNotifiers(u);
 
 
 
 #include <string>
 #include <list>
+#include <mutex>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
 #include <cstdint>
 
-#include <pthread.h>
-
 class PING;
 
 namespace STG
     void GetUsers();
     void SetUserNotifiers(UserPtr u);
     void UnSetUserNotifiers(UserPtr u);
-    static void * Run(void * d);
+    void Run(std::stop_token token);
 
     mutable std::string errorStr;
     PING_SETTINGS pingSettings;
     STG::Users * users;
     std::list<UserPtr> usersList;
 
-    pthread_t thread;
-    pthread_mutex_t mutex;
-    bool nonstop;
+    std::jthread m_thread;
+    std::mutex m_mutex;
     bool isRunning;
     mutable STG_PINGER pinger;
 
 
 #include "rscript.h"
 
 #include "ur_functor.h"
-#include "send_functor.h"
 
 #include "stg/common.h"
 #include "stg/locker.h"
 REMOTE_SCRIPT::REMOTE_SCRIPT()
     : sendPeriod(15),
       halfPeriod(8),
-      nonstop(false),
       isRunning(false),
       users(NULL),
       sock(0),
       onDelUserNotifier(*this),
       logger(STG::PluginLogger::get("rscript"))
 {
-pthread_mutex_init(&mutex, NULL);
 }
 //-----------------------------------------------------------------------------
 REMOTE_SCRIPT::~REMOTE_SCRIPT()
 {
-pthread_mutex_destroy(&mutex);
 }
 //-----------------------------------------------------------------------------
-void * REMOTE_SCRIPT::Run(void * d)
+void REMOTE_SCRIPT::Run(std::stop_token token)
 {
 sigset_t signalSet;
 sigfillset(&signalSet);
 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
 
-REMOTE_SCRIPT * rs = static_cast<REMOTE_SCRIPT *>(d);
+isRunning = true;
 
-rs->isRunning = true;
-
-while (rs->nonstop)
+while (!token.stop_requested())
     {
-    rs->PeriodicSend();
+    PeriodicSend();
     sleep(2);
     }
 
-rs->isRunning = false;
-return NULL;
+isRunning = false;
 }
 //-----------------------------------------------------------------------------
 int REMOTE_SCRIPT::ParseSettings()
 {
 netRouters = rsSettings.GetSubnetsMap();
 
-InitEncrypt(&ctx, rsSettings.GetPassword());
+InitEncrypt(rsSettings.GetPassword());
 
 users->AddNotifierUserAdd(&onAddUserNotifier);
 users->AddNotifierUserDel(&onDelUserNotifier);
 
-nonstop = true;
-
 if (GetUsers())
     {
     return -1;
 
 if (!isRunning)
     {
-    if (pthread_create(&thread, NULL, Run, this))
-        {
-        errorStr = "Cannot create thread.";
-        logger("Cannot create thread.");
-        printfd(__FILE__, "Cannot create thread\n");
-        return -1;
-        }
+    m_thread = std::jthread([this](auto token){ Run(token); });
     }
 
 errorStr = "";
 if (!IsRunning())
     return 0;
 
-nonstop = false;
+m_thread.request_stop();
 
 std::for_each(
         authorizedUsers.begin(),
 if (isRunning)
     {
     logger("Cannot stop thread.");
-    return -1;
+    m_thread.detach();
     }
 
 return 0;
     }
 
     {
-    STG_LOCKER lock(&mutex);
+    std::lock_guard lock(m_mutex);
 
     printfd(__FILE__, "REMOTE_SCRIPT::Reload()\n");
 
 //-----------------------------------------------------------------------------
 void REMOTE_SCRIPT::PeriodicSend()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 
 std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
 while (it != authorizedUsers.end())
 RS::PACKET_HEADER packetHead;
 
 memset(packetHead.padding, 0, sizeof(packetHead.padding));
-strcpy((char*)packetHead.magic, RS_ID);
+memcpy(packetHead.magic, RS_ID, sizeof(RS_ID));
 packetHead.protoVer[0] = '0';
 packetHead.protoVer[1] = '2';
 if (forceDisconnect)
 
 packetHead.ip = htonl(rsu.ip);
 packetHead.id = htonl(rsu.user->GetID());
-strncpy((char*)packetHead.login, rsu.user->GetLogin().c_str(), RS_LOGIN_LEN);
+strncpy(reinterpret_cast<char*>(packetHead.login), rsu.user->GetLogin().c_str(), RS_LOGIN_LEN);
 packetHead.login[RS_LOGIN_LEN - 1] = 0;
 
 memcpy(buf, &packetHead, sizeof(packetHead));
 RS::PACKET_TAIL packetTail;
 
 memset(packetTail.padding, 0, sizeof(packetTail.padding));
-strcpy((char*)packetTail.magic, RS_ID);
+memcpy(packetTail.magic, RS_ID, sizeof(RS_ID));
 std::vector<std::string>::const_iterator it;
 std::string params;
 for(it = rsSettings.GetUserParams().begin();
     }
     params += parameter + " ";
     }
-strncpy((char *)packetTail.params, params.c_str(), RS_PARAMS_LEN);
+strncpy(reinterpret_cast<char*>(packetTail.params), params.c_str(), RS_PARAMS_LEN);
 packetTail.params[RS_PARAMS_LEN - 1] = 0;
 
 assert(sizeof(packetHead) + sizeof(packetTail) <= bufSize && "Insufficient buffer space");
 
-Encrypt(&ctx, buf + sizeof(packetHead), (char *)&packetTail, sizeof(packetTail) / 8);
+Encrypt(buf + sizeof(packetHead), reinterpret_cast<char *>(&packetTail), sizeof(packetTail) / 8);
 
 return false;
 }
     return true;
     }
 
-std::for_each(
-        rsu.routers.begin(),
-        rsu.routers.end(),
-        PacketSender(sock, buffer, sizeof(buffer), static_cast<uint16_t>(htons(rsSettings.GetPort())))
-        );
+for (const auto& ip : rsu.routers)
+{
+    struct sockaddr_in sendAddr;
+
+    sendAddr.sin_family = AF_INET;
+    sendAddr.sin_port = htons(rsSettings.GetPort());
+    sendAddr.sin_addr.s_addr = ip;
+
+    return sendto(sock, buffer, sizeof(buffer), 0, reinterpret_cast<struct sockaddr*>(&sendAddr), sizeof(sendAddr));
+}
 
 return false;
 }
 struct sockaddr_in sendAddr;
 
 sendAddr.sin_family = AF_INET;
-sendAddr.sin_port = static_cast<uint16_t>(htons(rsSettings.GetPort()));
+sendAddr.sin_port = htons(rsSettings.GetPort());
 sendAddr.sin_addr.s_addr = routerIP;
 
-ssize_t res = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));
+ssize_t res = sendto(sock, buffer, sizeof(buffer), 0, reinterpret_cast<struct sockaddr *>(&sendAddr), sizeof(sendAddr));
 
 if (res < 0)
     logger("sendto error: %s", strerror(errno));
 //-----------------------------------------------------------------------------
 std::vector<uint32_t> REMOTE_SCRIPT::IP2Routers(uint32_t ip)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 for (size_t i = 0; i < netRouters.size(); ++i)
     {
     if ((ip & netRouters[i].subnetMask) == (netRouters[i].subnetIP & netRouters[i].subnetMask))
 RS::USER rsu(IP2Routers(user->GetCurrIP()), user);
 Send(rsu);
 
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 authorizedUsers.insert(std::make_pair(user->GetCurrIP(), rsu));
 }
 //-----------------------------------------------------------------------------
 void REMOTE_SCRIPT::DelRSU(UserPtr user)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard lock(m_mutex);
 std::map<uint32_t, RS::USER>::iterator it(authorizedUsers.begin());
 while (it != authorizedUsers.end())
     {
     rs.DelRSU(user);
 }
 //-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const
+void REMOTE_SCRIPT::InitEncrypt(const std::string & password) const
 {
 unsigned char keyL[PASSWD_LEN];  // Пароль для шифровки
 memset(keyL, 0, PASSWD_LEN);
-strncpy((char *)keyL, password.c_str(), PASSWD_LEN);
-Blowfish_Init(ctx, keyL, PASSWD_LEN);
+strncpy(reinterpret_cast<char*>(keyL), password.c_str(), PASSWD_LEN);
+Blowfish_Init(&ctx, keyL, PASSWD_LEN);
 }
 //-----------------------------------------------------------------------------
-void REMOTE_SCRIPT::Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const
+void REMOTE_SCRIPT::Encrypt(void * dst, const void * src, size_t len8) const
 {
 if (dst != src)
     memcpy(dst, src, len8 * 8);
 for (size_t i = 0; i < len8; ++i)
-    Blowfish_Encrypt(ctx, static_cast<uint32_t *>(dst) + i * 2, static_cast<uint32_t *>(dst) + i * 2 + 1);
+    Blowfish_Encrypt(&ctx, static_cast<uint32_t *>(dst) + i * 2, static_cast<uint32_t *>(dst) + i * 2 + 1);
 }
 //-----------------------------------------------------------------------------
 
 #include <map>
 #include <functional>
 #include <utility>
+#include <mutex>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
 #include <cstdint>
 
-#include <pthread.h>
-
 namespace STG
 {
 struct Settings;
     REMOTE_SCRIPT(const REMOTE_SCRIPT & rhs);
     REMOTE_SCRIPT & operator=(const REMOTE_SCRIPT & rhs);
 
-    static void *       Run(void *);
+    void                Run(std::stop_token token);
     bool                PrepareNet();
     bool                FinalizeNet();
 
     void                SetUserNotifiers(UserPtr u);
     void                UnSetUserNotifiers(UserPtr u);
 
-    void                InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) const;
-    void                Encrypt(BLOWFISH_CTX * ctx, void * dst, const void * src, size_t len8) const;
+    void                InitEncrypt(const std::string & password) const;
+    void                Encrypt(void * dst, const void * src, size_t len8) const;
 
     mutable BLOWFISH_CTX ctx;
 
     int                 sendPeriod;
     int                 halfPeriod;
 
-    bool                nonstop;
     bool                isRunning;
 
     STG::Users *             users;
 
     std::vector<NET_ROUTER> netRouters;
 
-    pthread_t           thread;
-    pthread_mutex_t     mutex;
+    std::jthread        m_thread;
+    std::mutex          m_mutex;
 
     int                 sock;
 
 
+++ /dev/null
-/*
- *    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 : Maxim Mamontov <faust@stargazer.dp.ua>
- */
-
-/*
- $Revision: 1.2 $
- $Date: 2010/03/04 12:11:09 $
- $Author: faust $
-*/
-
-#ifndef __SEND_FUNCTOR_H__
-#define __SEND_FUNCTOR_H__
-
-#include <functional>
-#include <cstdint>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-
-class PacketSender : public std::unary_function<uint32_t, ssize_t> {
-    public:
-        PacketSender(int s, char * b, size_t l, uint16_t p)
-            : sock(s),
-              buffer(b),
-              length(l),
-              port(p) {}
-        ssize_t operator() (uint32_t ip)
-        {
-        struct sockaddr_in sendAddr;
-
-        sendAddr.sin_family = AF_INET;
-        sendAddr.sin_port = port;
-        sendAddr.sin_addr.s_addr = ip;
-
-        return sendto(sock, buffer, length, 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
-        }
-    private:
-        int sock;
-        char * buffer;
-        size_t length;
-        uint16_t port;
-};
-
-#endif
 
       services(NULL),
       corporations(NULL),
       traffcounter(NULL),
-      running(false),
       stopped(true),
       needReconnect(false),
       lastReconnectTry(0),
       addDelTariffNotifier(*this),
       logger(STG::PluginLogger::get("smux"))
 {
-pthread_mutex_init(&mutex, NULL);
-
 smuxHandlers[SMUX_PDUs_PR_close] = &SMUX::CloseHandler;
 smuxHandlers[SMUX_PDUs_PR_registerResponse] = &SMUX::RegisterResponseHandler;
 smuxHandlers[SMUX_PDUs_PR_pdus] = &SMUX::PDUsRequestHandler;
         delete it->second;
     }
 printfd(__FILE__, "SMUX::~SMUX()\n");
-pthread_mutex_destroy(&mutex);
 }
 
 int SMUX::ParseSettings()
     }
 #endif
 
-if (!running)
-    {
-    if (pthread_create(&thread, NULL, Runner, this))
-        {
-        errorStr = "Cannot create thread.";
-       logger("Cannot create thread.");
-        printfd(__FILE__, "Cannot create thread\n");
-        return -1;
-        }
-    }
+if (!m_thread.joinable())
+    m_thread = std::jthread([this](auto token){ Run(token); });
 
 return 0;
 }
 int SMUX::Stop()
 {
 printfd(__FILE__, "SMUX::Stop() - Before\n");
-running = false;
+m_thread.request_stop();
 
 if (!stopped)
     {
         }
     }
 
-if (stopped)
-    pthread_join(thread, NULL);
+if (!stopped)
+    m_thread.detach();
 
 ResetNotifiers();
 
 
 if (!stopped)
     {
-    running = true;
     return -1;
     }
 
 return 0;
 }
 
-void * SMUX::Runner(void * d)
-{
-sigset_t signalSet;
-sigfillset(&signalSet);
-pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
-
-SMUX * smux = static_cast<SMUX *>(d);
-
-smux->Run();
-
-return NULL;
-}
-
-void SMUX::Run()
+void SMUX::Run(std::stop_token token)
 {
 stopped = true;
 if (!SendOpenPDU(sock))
     needReconnect = true;
 if (!SendRReqPDU(sock))
     needReconnect = true;
-running = true;
 stopped = false;
 
-while(running)
+while (!token.stop_requested())
     {
     if (WaitPackets(sock) && !needReconnect)
         {
             DispatchPDUs(pdus);
             ASN_STRUCT_FREE(asn_DEF_SMUX_PDUs, pdus);
             }
-        else if (running)
+        else if (!token.stop_requested())
             Reconnect();
         }
-    else if (running && needReconnect)
+    else if (!token.stop_requested() && needReconnect)
         Reconnect();
-    if (!running)
+    if (token.stop_requested())
         break;
     }
 SendClosePDU(sock);
     }
 if (!done)
     {
-    Sensors::iterator it(newSensors.begin());
-    while (it != newSensors.end())
+    Sensors::iterator sit(newSensors.begin());
+    while (sit != newSensors.end())
         {
-        delete it->second;
-        ++it;
+        delete sit->second;
+        ++sit;
         }
     return false;
     }
 
 #ifndef __SMUX_H__
 #define __SMUX_H__
 
-#include <pthread.h>
-
 #include <string>
 #include <map>
 #include <list>
+#include <mutex>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
 #include <cstdint>
 
 #include "stg/SMUX-PDUs.h"
     int Start();
     int Stop();
     int Reload(const STG::ModuleSettings & ms);
-    bool IsRunning() { return running && !stopped; }
+    bool IsRunning() { return m_thread.joinable() && !stopped; }
 
     const std::string & GetStrError() const { return errorStr; }
     std::string GetVersion() const { return "Stg SMUX Plugin 1.1"; }
     SMUX(const SMUX & rvalue);
     SMUX & operator=(const SMUX & rvalue);
 
-    static void * Runner(void * d);
-    void Run();
+    void Run(std::stop_token token);
     bool PrepareNet();
     bool Reconnect();
 
     SMUX_SETTINGS smuxSettings;
     STG::ModuleSettings settings;
 
-    pthread_t thread;
-    pthread_mutex_t mutex;
-    bool running;
+    std::jthread m_thread;
+    std::mutex m_mutex;
     bool stopped;
     bool needReconnect;
 
 
               tariffs(t),
               users(u)
         {}
-        virtual ~TariffUsersTable() {}
 
-        void UpdateSensors(Sensors & sensors) const;
+        void UpdateSensors(Sensors & sensors) const override;
 
     private:
         STG::Tariffs & tariffs;
 
 size_t arcPos = 0;
 while ((left - str) < length)
     {
-    char * pos = NULL;
-    unsigned arc = static_cast<unsigned int>(strtoul(left, &pos, 10));
-    if (pos == left)
+    char * p = NULL;
+    unsigned arc = static_cast<unsigned int>(strtoul(left, &p, 10));
+    if (p == left)
         return false;
     a[arcPos++] = arc;
     if (arcPos >= 1024)
         return false;
-    left = pos + 1;
+    left = p + 1;
     }
 *pos = arcPos;
 return true;
 
 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
 IBPP::Statement st = IBPP::StatementFactory(db, tr);
 
-std::string login;
-
 try
     {
     tr->Start();
     st->Execute("select login from tb_admins");
     while (st->Fetch())
         {
+        std::string login;
         st->Get(1, login);
         adminsList->push_back(login);
         }
 
 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
 IBPP::Statement st = IBPP::StatementFactory(db, tr);
 
-std::string name;
-
 try
     {
     tr->Start();
     st->Execute("select name from tb_corporations");
     while (st->Fetch())
         {
+        std::string name;
         st->Get(1, name);
         corpsList->push_back(name);
         }
 
 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
 IBPP::Statement st = IBPP::StatementFactory(db, tr);
 
-std::string name;
-
 try
     {
     tr->Start();
     st->Execute("select name from tb_services");
     while (st->Fetch())
         {
+        std::string name;
         st->Get(1, name);
         servicesList->push_back(name);
         }
 
 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
 IBPP::Statement st = IBPP::StatementFactory(db, tr);
 
-std::string name;
-
 try
     {
     tr->Start();
     st->Execute("select name from tb_tariffs");
     while (st->Fetch())
         {
+        std::string name;
         st->Get(1, name);
         tariffsList->push_back(name);
         }
 
 IBPP::Transaction tr = IBPP::TransactionFactory(db, IBPP::amRead, til, tlr);
 IBPP::Statement st = IBPP::StatementFactory(db, tr);
 
-std::string name;
-
 try
     {
     tr->Start();
     st->Execute("select name from tb_users");
     while (st->Fetch())
         {
+        std::string name;
         st->Get(1, name);
         usersList->push_back(name);
         }
     st->Execute();
 
     st->Prepare("insert into tb_allowed_ip (fk_user, ip, mask) values (?, ?, ?)");
-    for(size_t i = 0; i < conf.ips.count(); i++)
+    for(size_t j = 0; i < conf.ips.count(); j++)
         {
         st->Set(1, uid);
-        st->Set(2, (int32_t)conf.ips[i].ip);
-        st->Set(3, (int32_t)conf.ips[i].mask);
+        st->Set(2, (int32_t)conf.ips[j].ip);
+        st->Set(3, (int32_t)conf.ips[j].mask);
         st->Execute();
         }
     tr->Commit();
 
     errorStr = "Couldn't get tables list With error:\n";
     errorStr += mysql_error(sock);
     mysql_close(sock);
-    return -1;
+    return false;
 }
 
 my_ulonglong num_rows =  mysql_num_rows(result);
 
 
 struct Error : public std::runtime_error
 {
-    Error(const std::string& message) : runtime_error(message) {}
+    explicit Error(const std::string& message) : runtime_error(message) {}
 };
 
 std::vector<std::string> toValues(const DOTCONFDocumentNode& node)
 
       WriteServLog(Logger::get()),
       noTariff(NO_TARIFF_NAME)
 {
-ReadTariffs();
 }
 //-----------------------------------------------------------------------------
 int TariffsImpl::ReadTariffs()
 
       monitoring(false),
       touchTimeP(stgTime - MONITOR_TIME_DELAY_SEC),
       users(u),
-      running(false),
       stopped(true),
       addUserNotifier(*this),
       delUserNotifier(*this)
 
 users->AddNotifierUserAdd(&addUserNotifier);
 users->AddNotifierUserDel(&delUserNotifier);
-
-pthread_mutex_init(&mutex, NULL);
 }
 //-----------------------------------------------------------------------------
 TraffCounterImpl::~TraffCounterImpl()
 {
-pthread_mutex_destroy(&mutex);
 }
 //-----------------------------------------------------------------------------
 int TraffCounterImpl::Start()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 if (!stopped)
     return 0;
     SetUserNotifiers(u);
 users->CloseSearch(h);
 
-running = true;
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    printfd(__FILE__, "TraffCounterImpl::Start() - Cannot start thread\n");
-    WriteServLog("TraffCounter: Error: Cannot start thread.");
-    return -1;
-    }
+m_thread = std::jthread([this](auto token){ Run(token); });
 return 0;
 }
 //-----------------------------------------------------------------------------
 if (stopped)
     return 0;
 
-running = false;
+m_thread.request_stop();
 
 int h = users->OpenSearch();
 assert(h && "USERS::OpenSearch is always correct");
     }
 
 if (!stopped)
+{
+    m_thread.detach();
     return -1;
+}
 
 printfd(__FILE__, "TraffCounter::Stop()\n");
 
 return 0;
 }
 //-----------------------------------------------------------------------------
-void * TraffCounterImpl::Run(void * data)
+void TraffCounterImpl::Run(std::stop_token token)
 {
 sigset_t signalSet;
 sigfillset(&signalSet);
 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
 
-TraffCounterImpl * tc = static_cast<TraffCounterImpl *>(data);
-tc->stopped = false;
+stopped = false;
 int c = 0;
 
 time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
 struct timespec ts = {0, 500000000};
-while (tc->running)
+while (!token.stop_requested())
     {
     nanosleep(&ts, 0);
-    if (!tc->running)
+    if (token.stop_requested())
         {
-        tc->FlushAndRemove();
+        FlushAndRemove();
         break;
         }
 
-    if (tc->monitoring && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
+    if (monitoring && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
         {
-        std::string monFile(tc->monitorDir + "/traffcounter_r");
-        printfd(__FILE__, "Monitor=%d file TraffCounter %s\n", tc->monitoring, monFile.c_str());
+        std::string monFile(monitorDir + "/traffcounter_r");
+        printfd(__FILE__, "Monitor=%d file TraffCounter %s\n", monitoring, monFile.c_str());
         touchTime = stgTime;
         TouchFile(monFile);
         }
 
     if (++c % FLUSH_TIME == 0)
-        tc->FlushAndRemove();
+        FlushAndRemove();
     }
 
-tc->stopped = true;
-return NULL;
+stopped = true;
 }
 //-----------------------------------------------------------------------------
 void TraffCounterImpl::process(const RawPacket & rawPacket)
 {
-if (!running)
-    return;
-
 if (monitoring && (touchTimeP + MONITOR_TIME_DELAY_SEC <= stgTime))
     {
     std::string monFile = monitorDir + "/traffcounter_p";
     TouchFile(monFile);
     }
 
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 //printfd(__FILE__, "TraffCounter::Process()\n");
 //TODO replace find with lower_bound.
 //-----------------------------------------------------------------------------
 void TraffCounterImpl::FlushAndRemove()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 Packets::size_type oldPacketsSize = packets.size();
 Index::size_type oldIp2packetsSize = ip2packets.size();
 uint32_t uip = user->GetCurrIP();
 std::pair<ip2p_iter, ip2p_iter> pi;
 
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 // Find all packets with IP belongs to this user
 pi = ip2packets.equal_range(uip);
 
 printfd(__FILE__, "DelUser: %s \n", inet_ntostring(uip).c_str());
 std::pair<ip2p_iter, ip2p_iter> pi;
 
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 pi = ip2packets.equal_range(uip);
 
 while (pi.first != pi.second)
 //-----------------------------------------------------------------------------
 int TraffCounterImpl::Reload()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 if (ReadRules(true))
     {
 
 #include <list>
 #include <map>
 #include <string>
+#include <mutex>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
 #include <cstdint>
 
-#include <pthread.h>
-
 #define PROTOMAX    (5)
 
 namespace STG
         void        FreeRules();
         bool        ReadRules(bool test = false);
 
-        static void * Run(void * data);
+        void        Run(std::stop_token token);
 
         void        DeterminateDir(const RawPacket & packet,
                                    int * dirU, // Direction for upload
 
         UsersImpl *             users;
 
-        bool                     running;
         bool                     stopped;
-        pthread_mutex_t          mutex;
-        pthread_t                thread;
+        std::mutex               m_mutex;
+        std::jthread             m_thread;
 
         std::list<TRF_IP_BEFORE> ipBeforeNotifiers;
         std::list<TRF_IP_AFTER>  ipAfterNotifiers;
 
 
 #include <algorithm>
 #include <functional>
+#include <array>
 
 #include <cassert>
 #include <cstdlib>
 {
 STG_LOCKER lock(&mutex);
 
-if (stgTime > static_cast<time_t>(lastWriteStat + settings->GetStatWritePeriod()))
+if (stgTime > lastWriteStat + settings->GetStatWritePeriod())
     {
     printfd(__FILE__, "UserImpl::WriteStat user=%s\n", GetLogin().c_str());
     WriteStat();
 {
 STG_LOCKER lock(&mutex);
 
-static int daysInMonth[12] =
-{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static const std::array<unsigned, 12> daysInMonth{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
 struct tm tms;
 time_t t = stgTime;
 
       store(st),
       sysAdmin(sa),
       WriteServLog(Logger::get()),
-      nonstop(false),
       isRunning(false),
       handle(0)
 {
-pthread_mutexattr_t attr;
-pthread_mutexattr_init(&attr);
-pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-pthread_mutex_init(&mutex, &attr);
 }
 //-----------------------------------------------------------------------------
 UsersImpl::~UsersImpl()
 {
-pthread_mutex_destroy(&mutex);
 }
 //-----------------------------------------------------------------------------
 int UsersImpl::FindByNameNonLock(const std::string & login, user_iter * user)
 //-----------------------------------------------------------------------------
 int UsersImpl::FindByName(const std::string & login, UserPtr * user)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 user_iter u;
 if (FindByNameNonLock(login, &u))
     return -1;
 //-----------------------------------------------------------------------------
 int UsersImpl::FindByName(const std::string & login, ConstUserPtr * user) const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 const_user_iter u;
 if (FindByNameNonLock(login, &u))
     return -1;
 //-----------------------------------------------------------------------------
 bool UsersImpl::Exists(const std::string & login) const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 const std::map<std::string, user_iter>::const_iterator iter(loginIndex.find(login));
 return iter != loginIndex.end();
 }
 //-----------------------------------------------------------------------------
 bool UsersImpl::TariffInUse(const std::string & tariffName) const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 std::list<UserImpl>::const_iterator iter;
 iter = users.begin();
 while (iter != users.end())
 //-----------------------------------------------------------------------------
 int UsersImpl::Add(const std::string & login, const Admin * admin)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 const auto& priv = admin->priv();
 
 if (!priv.userAddDel)
 
 
     {
-    STG_LOCKER lock(&mutex);
+    std::lock_guard<std::mutex> lock(m_mutex);
 
     if (FindByNameNonLock(login, &u))
         {
     }
 
     {
-    STG_LOCKER lock(&mutex);
+    std::lock_guard<std::mutex> lock(m_mutex);
 
     u->OnDelete();
 
                            uint32_t enabledDirs, const Auth * auth)
 {
 user_iter iter;
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 if (FindByNameNonLock(login, &iter))
     {
     WriteServLog("Attempt to authorize non-existant user '%s'", login.c_str());
                              const std::string & reason)
 {
 user_iter iter;
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 if (FindByNameNonLock(login, &iter))
     {
     WriteServLog("Attempt to unauthorize non-existant user '%s'", login.c_str());
 return 0;
 }
 //-----------------------------------------------------------------------------
-void * UsersImpl::Run(void * d)
+void UsersImpl::Run(std::stop_token token)
 {
 sigset_t signalSet;
 sigfillset(&signalSet);
 pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
 
 printfd(__FILE__, "=====================| pid: %d |===================== \n", getpid());
-UsersImpl * us = static_cast<UsersImpl *>(d);
 
 struct tm t;
 time_t tt = stgTime;
 printfd(__FILE__,"Day = %d Min = %d\n", day, min);
 
 time_t touchTime = stgTime - MONITOR_TIME_DELAY_SEC;
-std::string monFile = us->settings->GetMonitorDir() + "/users_r";
-printfd(__FILE__, "Monitor=%d file USERS %s\n", us->settings->GetMonitoring(), monFile.c_str());
+std::string monFile = settings->GetMonitorDir() + "/users_r";
+printfd(__FILE__, "Monitor=%d file USERS %s\n", settings->GetMonitoring(), monFile.c_str());
 
-us->isRunning = true;
-while (us->nonstop)
+isRunning = true;
+while (!token.stop_requested())
     {
     //printfd(__FILE__,"New Minute. old = %02d current = %02d\n", min, t->tm_min);
     //printfd(__FILE__,"New Day.    old = %2d current = %2d\n", day, t->tm_mday);
 
-    for_each(us->users.begin(), us->users.end(), [](auto& user){ user.Run(); });
+    for_each(users.begin(), users.end(), [](auto& user){ user.Run(); });
 
     tt = stgTime;
     localtime_r(&tt, &t);
         printfd(__FILE__,"New Minute. old = %d current = %d\n", min, t.tm_min);
         min = t.tm_min;
 
-        us->NewMinute(t);
+        NewMinute(t);
         }
 
     if (day != t.tm_mday)
         printfd(__FILE__,"Sec = %d\n", stgTime);
         printfd(__FILE__,"New Day. old = %d current = %d\n", day, t.tm_mday);
         day = t.tm_mday;
-        us->NewDay(t);
+        NewDay(t);
         }
 
-    if (us->settings->GetMonitoring() && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
+    if (settings->GetMonitoring() && (touchTime + MONITOR_TIME_DELAY_SEC <= stgTime))
         {
         //printfd(__FILE__, "Monitor=%d file TRAFFCOUNTER %s\n", tc->monitoring, monFile.c_str());
         touchTime = stgTime;
         }
 
     stgUsleep(100000);
-    } //while (us->nonstop)
+    }
 
-std::list<USER_TO_DEL>::iterator iter(us->usersToDelete.begin());
-while (iter != us->usersToDelete.end())
+std::list<USER_TO_DEL>::iterator iter(usersToDelete.begin());
+while (iter != usersToDelete.end())
     {
     iter->delTime -= 2 * userDeleteDelayTime;
     ++iter;
     }
-us->RealDelUser();
+RealDelUser();
 
-us->isRunning = false;
+isRunning = false;
 
-return NULL;
 }
 //-----------------------------------------------------------------------------
 void UsersImpl::NewMinute(const struct tm & t)
     return -1;
     }
 
-nonstop = true;
-if (pthread_create(&thread, NULL, Run, this))
-    {
-    WriteServLog("USERS: Error: Cannot start thread!");
-    return -1;
-    }
+m_thread = std::jthread([this](auto token){ Run(token); });
 return 0;
 }
 //-----------------------------------------------------------------------------
 {
 printfd(__FILE__, "USERS::Stop()\n");
 
-if (!isRunning)
-    {
-    //printfd(__FILE__, "Alredy stopped\n");
-    return 0;
-    }
-
-nonstop = false;
+m_thread.request_stop();
 
 //5 seconds to thread stops itself
 struct timespec ts = {0, 200000000};
 //after 5 seconds waiting thread still running. now kill it
 if (isRunning)
     {
-    printfd(__FILE__, "kill USERS thread.\n");
+    printfd(__FILE__, "Detach USERS thread.\n");
     //TODO pthread_cancel()
-    if (pthread_kill(thread, SIGINT))
-        {
-        //errorStr = "Cannot kill USERS thread.";
-        //printfd(__FILE__, "Cannot kill USERS thread.\n");
-        //return 0;
-        }
-    printfd(__FILE__, "USERS killed\n");
+    m_thread.detach();
     }
 
 printfd(__FILE__, "Before USERS::Run()\n");
 //-----------------------------------------------------------------------------
 void UsersImpl::RealDelUser()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 printfd(__FILE__, "RealDelUser() users to del: %d\n", usersToDelete.size());
 
 if (!ip)
     return; // User has disconnected
 
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 const std::map<uint32_t, user_iter>::iterator it(
         ipIndex.lower_bound(ip)
 printfd(__FILE__, "USERS: Del IP Idx\n");
 assert(ip && "User has non-null ip");
 
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 const std::map<uint32_t, user_iter>::iterator it(
         ipIndex.find(ip)
 //-----------------------------------------------------------------------------
 int UsersImpl::FindByIPIdx(uint32_t ip, UserPtr * usr) const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 user_iter iter;
 if (FindByIPIdx(ip, iter))
 //-----------------------------------------------------------------------------
 int UsersImpl::FindByIPIdx(uint32_t ip, UserImpl ** usr) const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 user_iter iter;
 if (FindByIPIdx(ip, iter))
 //-----------------------------------------------------------------------------
 bool UsersImpl::IsIPInIndex(uint32_t ip) const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 std::map<uint32_t, user_iter>::const_iterator it(ipIndex.find(ip));
 
 //-----------------------------------------------------------------------------
 bool UsersImpl::IsIPInUse(uint32_t ip, const std::string & login, ConstUserPtr * user) const
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 std::list<UserImpl>::const_iterator iter;
 iter = users.begin();
 while (iter != users.end())
 //-----------------------------------------------------------------------------
 void UsersImpl::AddNotifierUserAdd(NotifierBase<UserPtr> * n)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 onAddNotifiers.insert(n);
 }
 //-----------------------------------------------------------------------------
 void UsersImpl::DelNotifierUserAdd(NotifierBase<UserPtr> * n)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 onAddNotifiers.erase(n);
 }
 //-----------------------------------------------------------------------------
 void UsersImpl::AddNotifierUserDel(NotifierBase<UserPtr> * n)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 onDelNotifiers.insert(n);
 }
 //-----------------------------------------------------------------------------
 void UsersImpl::DelNotifierUserDel(NotifierBase<UserPtr> * n)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 onDelNotifiers.erase(n);
 }
 //-----------------------------------------------------------------------------
 void UsersImpl::AddNotifierUserAdd(NotifierBase<UserImplPtr> * n)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 onAddNotifiersImpl.insert(n);
 }
 //-----------------------------------------------------------------------------
 void UsersImpl::DelNotifierUserAdd(NotifierBase<UserImplPtr> * n)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 onAddNotifiersImpl.erase(n);
 }
 //-----------------------------------------------------------------------------
 void UsersImpl::AddNotifierUserDel(NotifierBase<UserImplPtr> * n)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 onDelNotifiersImpl.insert(n);
 }
 //-----------------------------------------------------------------------------
 void UsersImpl::DelNotifierUserDel(NotifierBase<UserImplPtr> * n)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 onDelNotifiersImpl.erase(n);
 }
 //-----------------------------------------------------------------------------
 int UsersImpl::OpenSearch()
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 handle++;
 searchDescriptors[handle] = users.begin();
 return handle;
 //-----------------------------------------------------------------------------
 int UsersImpl::SearchNext(int h, UserImpl ** user)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 
 if (searchDescriptors.find(h) == searchDescriptors.end())
     {
 //-----------------------------------------------------------------------------
 int UsersImpl::CloseSearch(int h)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 if (searchDescriptors.find(h) != searchDescriptors.end())
     {
     searchDescriptors.erase(searchDescriptors.find(h));
 //-----------------------------------------------------------------------------
 void UsersImpl::AddUserIntoIndexes(user_iter user)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 loginIndex.insert(make_pair(user->GetLogin(), user));
 }
 //-----------------------------------------------------------------------------
 void UsersImpl::DelUserFromIndexes(user_iter user)
 {
-STG_LOCKER lock(&mutex);
+std::lock_guard<std::mutex> lock(m_mutex);
 loginIndex.erase(user->GetLogin());
 }
 //-----------------------------------------------------------------------------
 
 #include <map>
 #include <list>
 #include <set>
+#include <mutex>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include <jthread.hpp>
+#pragma GCC diagnostic pop
 #include <ctime>
 #include <cstdint>
 
     void            AddUserIntoIndexes(user_iter user);
     void            DelUserFromIndexes(user_iter user);
 
-    static void *   Run(void *);
+    void            Run(std::stop_token token);
     void            NewMinute(const struct tm & t);
     void            NewDay(const struct tm & t);
     void            DayResetTraff(const struct tm & t);
     const Admin&       sysAdmin;
     Logger &        WriteServLog;
 
-    bool                nonstop;
     bool                isRunning;
 
-    mutable pthread_mutex_t mutex;
-    pthread_t               thread;
+    mutable std::mutex      m_mutex;
+    std::jthread            m_thread;
     mutable unsigned int    handle;
 
     mutable std::map<int, user_iter>  searchDescriptors;
 
 target_link_libraries ( tests conffiles crypto logger scriptexecuter common Threads::Threads )
 
 target_include_directories ( tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ../projects/stargazer )
+
+add_test ( tests tests )
 
         TEST_SETTINGS_LOCAL settings;
         settings.addFilter("*"); // Allow everything by default.
         TEST_TARIFFS tariffs;
+        tariffs.ReadTariffs();
         STG::Admin admin(STG::Priv(0xFFFF), {}, {});
         TEST_STORE_LOCAL store;
         TEST_AUTH auth;
 
 
         TEST_SETTINGS_LOCAL settings(false);
         TEST_TARIFFS tariffs;
+        tariffs.ReadTariffs();
         STG::Admin admin(STG::Priv(0xFFFF), {}, {});
         TEST_STORE store;
         TEST_AUTH auth;