]> git.stg.codes - stg.git/commitdiff
Добавляю экспериментальный плагин конфигуратора. Проект полумертв, но
authorMaxim Mamontov <faust@user-desktop.(none)>
Mon, 8 Nov 2010 10:38:13 +0000 (12:38 +0200)
committerMaxim Mamontov <faust@user-desktop.(none)>
Mon, 8 Nov 2010 10:38:13 +0000 (12:38 +0200)
там есть интересные наработки. Так что пусть будет.

18 files changed:
projects/stargazer/plugins/configuration/sgconfig-ng/Makefile [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/config_thread.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/config_thread.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/creator.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/main_thread.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/main_thread.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/parser.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/parser_getuser.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/parser_getuser.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/parser_getusers.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/parser_getusers.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/parser_info.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/parser_info.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/proto.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/root_parser.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/root_parser.h [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/stgconfig.cpp [new file with mode: 0644]
projects/stargazer/plugins/configuration/sgconfig-ng/stgconfig.h [new file with mode: 0644]

diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/Makefile b/projects/stargazer/plugins/configuration/sgconfig-ng/Makefile
new file mode 100644 (file)
index 0000000..13bf548
--- /dev/null
@@ -0,0 +1,23 @@
+###############################################################################
+# $Id: Makefile,v 1.9 2008/12/04 17:09:40 faust Exp $
+###############################################################################
+
+include ../../../../../Makefile.conf
+
+PROG = mod_conf_sg-ng.so
+
+SRCS = ./stgconfig.cpp \
+       ./creator.cpp \
+       ./main_thread.cpp \
+       ./config_thread.cpp \
+       ./root_parser.cpp \
+       ./parser_info.cpp \
+       ./parser_getuser.cpp \
+       ./parser_getusers.cpp
+
+LIBS += -lexpat \
+       -lboost_thread-mt
+
+STGLIBS = -lstg_common -lstg_logger -lcrypto
+
+include ../../Makefile.in
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/config_thread.cpp b/projects/stargazer/plugins/configuration/sgconfig-ng/config_thread.cpp
new file mode 100644 (file)
index 0000000..38d6d85
--- /dev/null
@@ -0,0 +1,429 @@
+#include <expat.h>
+
+#include <cstring>
+#include <cerrno>
+#include <cassert>
+#include <iostream>
+
+#include <boost/thread/mutex.hpp>
+
+// TODO: Fix this shit!
+#include "../../../admins.h"
+
+#include "common.h"
+#include "proto.h"
+#include "config_thread.h"
+#include "root_parser.h"
+
+void DumpCrypto(const char * data, size_t size)
+{
+    std::string dumpstr = "";
+    for (unsigned i = 0; i < size; ++i) {
+        std::string ch;
+        strprintf(&ch, "%x", *(data + i));
+        dumpstr += ch;
+    }
+    printfd(__FILE__, "Crypto dump: '%s'\n", dumpstr.c_str());
+}
+
+CONFIG_THREAD::CONFIG_THREAD(ADMINS * a, TARIFFS * t, USERS * u, const SETTINGS * s)
+    : sd(-1),
+      done(false),
+      state(ST_NOOP),
+      respCode(RESP::OK),
+      admins(a),
+      tariffs(t),
+      users(u),
+      settings(s)
+{
+    /*printfd(__FILE__, "sizeof(REQ::HEADER) = %d\n", sizeof(REQ::HEADER));
+    printfd(__FILE__, "sizeof(REQ::CRYPTO_HEADER) = %d\n", sizeof(REQ::CRYPTO_HEADER));
+    printfd(__FILE__, "sizeof(RESP::HEADER) = %d\n", sizeof(RESP::HEADER));
+    printfd(__FILE__, "sizeof(RESP::CRYPTO_HEADER) = %d\n", sizeof(RESP::CRYPTO_HEADER));*/
+    assert(sizeof(REQ::HEADER) % 8 == 0);
+    assert(sizeof(REQ::CRYPTO_HEADER) % 8 == 0);
+    assert(sizeof(RESP::HEADER) % 8 == 0);
+    assert(sizeof(RESP::CRYPTO_HEADER) % 8 == 0);
+
+    iv = new unsigned char[8];
+    memset(iv, 0, 8);
+}
+
+CONFIG_THREAD::CONFIG_THREAD(const CONFIG_THREAD & rvalue)
+    : sd(rvalue.sd),
+      remoteAddr(rvalue.remoteAddr),
+      done(false),
+      state(ST_NOOP),
+      respCode(rvalue.respCode),
+      admins(rvalue.admins),
+      tariffs(rvalue.tariffs),
+      users(rvalue.users),
+      settings(rvalue.settings)
+{
+    assert(!rvalue.done);
+    iv = new unsigned char[8];
+    memcpy(iv, rvalue.iv, 8);
+}
+
+CONFIG_THREAD & CONFIG_THREAD::operator=(const CONFIG_THREAD & rvalue)
+{
+    assert(0 && "Never be here");
+    return *this;
+}
+
+CONFIG_THREAD::~CONFIG_THREAD()
+{
+    //assert(done);
+    delete[] iv;
+}
+
+void CONFIG_THREAD::operator() ()
+{
+    if (sd < 0) {
+        printfd(__FILE__, "CONFIG_THREAD::operator()() Invalid socket descriptor\n");
+        return;
+    }
+
+    if (ReadReq()) {
+        Process();
+    }
+
+    WriteResp();
+
+    close(sd);
+
+    {
+        boost::mutex::scoped_lock lock(mutex);
+        done = true;
+    }
+}
+
+bool CONFIG_THREAD::IsDone() const
+{
+    boost::mutex::scoped_lock lock(mutex);
+    return done;
+}
+
+void CONFIG_THREAD::SetConnection(int sock, struct sockaddr_in sin)
+{
+    sd = sock;
+    remoteAddr = sin;
+}
+
+bool CONFIG_THREAD::ReadBlock(void * dest, size_t & size, int timeout) const
+{
+    unsigned readSize = 0;
+    char * ptr = static_cast<char *>(dest);
+    while (readSize < size) {
+        struct timeval tv;
+        tv.tv_sec = 0;
+        tv.tv_usec = timeout * 1000;
+
+        fd_set rfds;
+        FD_ZERO(&rfds);
+        FD_SET(sd, &rfds);
+
+        int res = select(sd + 1, &rfds, NULL, NULL, &tv);
+        /* Don't rely on the value of tv now! */
+
+        if (res < 0) {
+            printfd(__FILE__, "CONFIG_THREAD::ReadBlock() Select error: '%s'\n", strerror(errno));
+            return false;
+        }
+
+        if (res == 0) {
+            // Timeout
+            size = readSize;
+            return false;
+        }
+
+        res = read(sd, ptr + readSize, size - readSize);
+
+        if (res == 0) { // EOF
+            printfd(__FILE__, "CONFIG_THREAD::ReadBlock() EOF\n");
+            return false;
+        }
+
+        // Ignore 'Interrupted system call' errors
+        if (res < 0) {
+            if (errno != EINTR) {
+                printfd(__FILE__, "CONFIG_THREAD::ReadBlock() Read error: '%s'\n", strerror(errno));
+                return false;
+            } else {
+                continue;
+            }
+        }
+
+        readSize += res;
+    }
+
+    return true;
+}
+
+bool CONFIG_THREAD::WriteBlock(const void * source, size_t & size, int timeout) const
+{
+    const char * ptr = static_cast<const char *>(source);
+    unsigned writeSize = 0;
+    while (writeSize < size) {
+        struct timeval tv;
+        tv.tv_sec = 0;
+        tv.tv_usec = timeout * 1000;
+
+        fd_set wfds;
+        FD_ZERO(&wfds);
+        FD_SET(sd, &wfds);
+
+        int res = select(sd + 1, NULL, &wfds, NULL, &tv);
+        /* Don't rely on the value of tv now! */
+
+        if (res < 0) {
+            printfd(__FILE__, "CONFIG_THREAD::WriteBlock() Select error: '%s'\n", strerror(errno));
+            return false;
+        }
+
+        if (res == 0) {
+            // Timeout
+            size = writeSize;
+            return false;
+        }
+
+        res = write(sd, ptr + writeSize, size - writeSize);
+
+        // Ignore 'Interrupted system call' errors
+        if (res < 0 && errno != EINTR) {
+            printfd(__FILE__, "CONFIG_THREAD::WriteBlock() Write error: '%s'\n", strerror(errno));
+            return false;
+        }
+
+        writeSize += res;
+    }
+
+    return true;
+}
+
+bool CONFIG_THREAD::ReadReq()
+{
+    struct REQ::HEADER reqHeader;
+
+    size_t size = sizeof(reqHeader);
+    if (!ReadBlock(&reqHeader, size, 5000)) {
+        state = ST_ERROR;
+        message = "No request header within 5 sec";
+        printfd(__FILE__, "CONFIG_THREAD::ReadReq() %s\n", message.c_str());
+        return false;
+    }
+
+    if (strncmp(reqHeader.magic, PROTO_MAGIC, sizeof(reqHeader.magic))) {
+        state = ST_ERROR;
+        respCode = RESP::INVALID_MAGIC;
+        message = "Invalid magic code in header";
+        printfd(__FILE__, "CONFIG_THREAD::ReadReq() %s\n", message.c_str());
+        return false;
+    }
+
+    uint32_t version = ntohl(reqHeader.version);
+    if (version > (2 << 8 | 0)) {
+        state = ST_ERROR;
+        respCode = RESP::UNSUPPORTED_VERSION;
+        message = "Unsupported version";
+        printfd(__FILE__, "CONFIG_THREAD::ReadReq() %s (wanted: %d, actual: %d)\n", message.c_str(), (2 << 8 | 0), version);
+        return false;
+    }
+
+    versionMinor = version & 0x0000FFFF;
+    versionMajor = (version >> 8) & 0x0000FFFF;
+
+    reqHeader.login[sizeof(reqHeader.login) - 1] = 0;
+
+    login = reqHeader.login;
+
+    if (!CheckLogin(login, password)) {
+        state = ST_ERROR;
+        respCode = RESP::INVALID_CREDENTIALS;
+        message = "Unknown login";
+        printfd(__FILE__, "CONFIG_THREAD::ReadReq() %s\n", message.c_str());
+        return false;
+    }
+
+    return ReceiveData();
+}
+
+bool CONFIG_THREAD::ReceiveData()
+{
+    unsigned char buffer[sizeof(struct REQ::CRYPTO_HEADER)];
+    //unsigned char iv[] = "00000000";
+    size_t size = sizeof(struct REQ::CRYPTO_HEADER);
+
+    if (!ReadBlock(buffer, size, 5000)) {
+        state = ST_ERROR;
+        message = "No crypto header within 5 secs";
+        printfd(__FILE__, "CONFIG_THREAD::ReceiveData() %s\n", message.c_str());
+        return false;
+    }
+
+    BF_set_key(&key, password.length(), reinterpret_cast<const unsigned char *>(password.c_str()));
+
+    struct REQ::CRYPTO_HEADER reqCryptoHeader;
+
+    BF_cbc_encrypt(buffer, reinterpret_cast<unsigned char *>(&reqCryptoHeader), sizeof(struct REQ::CRYPTO_HEADER), &key, iv, BF_DECRYPT);
+
+    reqCryptoHeader.login[sizeof(reqCryptoHeader.login) - 1] = 0;
+
+    std::string cryptoLogin(reqCryptoHeader.login);
+
+    if (login != cryptoLogin) {
+        state = ST_ERROR;
+        respCode = RESP::INVALID_CREDENTIALS;
+        message = "Password is invalid";
+        printfd(__FILE__, "CONFIG_THREAD::ReceiveData() %s\n", message.c_str());
+        return false;
+    }
+
+    //assert(reqCryptoHeader.dataSize % 8 == 0);
+
+    char block[1496];
+    unsigned char cryptoBlock[1496];
+    size_t length = 0;
+    uint32_t dataSize = ntohl(reqCryptoHeader.dataSize);
+
+    while (length < dataSize) {
+        size_t delta = dataSize - length;
+        if (delta > sizeof(cryptoBlock)) {
+            delta = sizeof(cryptoBlock);
+        }
+        size_t bs = delta;
+        ReadBlock(cryptoBlock, bs, 5000);
+        if (bs != delta) {
+            state = ST_ERROR;
+            message = "No data within 5 secs";
+            printfd(__FILE__, "CONFIG_THREAD::ReceiveData() %s\n", message.c_str());
+            return false;
+        }
+
+        BF_cbc_encrypt(cryptoBlock, reinterpret_cast<unsigned char *>(block), bs, &key, iv, BF_DECRYPT);
+
+        xml.append(block, bs);
+
+        length += bs;
+    }
+
+    return true;
+}
+
+void CONFIG_THREAD::Process()
+{
+    ROOT_PARSER parser(currAdmin, tariffs, users, settings);
+
+    XML_Parser p;
+
+    p= XML_ParserCreate(NULL);
+    XML_SetElementHandler(p, &TagBegin, &TagEnd);
+    XML_SetUserData(p, &parser);
+
+    if (!XML_Parse(p, xml.c_str(), xml.length(), true)) {
+        printfd(__FILE__, "CONFIG_THREAD::Process() Error: '%s' at line %d\n", XML_ErrorString(XML_GetErrorCode(p)), XML_GetCurrentLineNumber(p));
+        //MakeErrorXML();
+    }
+
+    XML_ParserFree(p);
+
+    xml = parser.GetResult();
+}
+
+void CONFIG_THREAD::WriteResp() const
+{
+    RESP::HEADER respHeader;
+
+    strncpy(respHeader.magic, PROTO_MAGIC, sizeof(respHeader.magic));
+    respHeader.version = htonl(2 << 8 | 0);
+    respHeader.code = respCode;
+
+    RESP::CRYPTO_HEADER respCryptoHeader;
+    strncpy(respCryptoHeader.login, login.c_str(), sizeof(respCryptoHeader.login));
+    if (xml.size() % 8 == 0) {
+        respCryptoHeader.dataSize = htonl(xml.size());
+    } else {
+        respCryptoHeader.dataSize = htonl((xml.size() / 8 + 1) * 8);
+    }
+
+    size_t size = sizeof(respHeader);
+    if (!WriteBlock(&respHeader, size, 5000)) {
+        printfd(__FILE__, "CONFIG_THREAD::WriteResp() Failed to send answer header\n");
+        return;
+    }
+
+    if (state != ST_ERROR) {
+        unsigned char buffer[sizeof(respCryptoHeader)];
+        size = sizeof(respCryptoHeader);
+
+        BF_cbc_encrypt(reinterpret_cast<unsigned char *>(&respCryptoHeader), buffer, size, &key, iv, BF_ENCRYPT);
+
+        if (!WriteBlock(buffer, size, 5000)) {
+            printfd(__FILE__, "CONFIG_THREAD::WriteResp() Failed to send answer crypto-header\n");
+            return;
+        }
+
+        SendData();
+    }
+}
+
+void CONFIG_THREAD::SendData() const
+{
+    size_t pos = 0;
+    std::string data(xml);
+    if (data.size() % 8) {
+        size_t delta = (data.size() / 8 + 1) * 8 - data.size();
+        data.append(delta, ' ');
+    }
+    while (pos < data.size()) {
+        unsigned char source[1496];
+        unsigned char buffer[1496];
+
+        size_t size;
+        if (data.size() - pos > sizeof(source)) {
+            memcpy(source, data.c_str() + pos, sizeof(source));
+            size = sizeof(source);
+        } else {
+            memset(source, 0, sizeof(source));
+            memcpy(source, data.c_str() + pos, data.size() - pos);
+            size = data.size() - pos;
+        }
+
+        BF_cbc_encrypt(source, buffer, size, &key, iv, BF_ENCRYPT);
+
+        if (!WriteBlock(buffer, size, 5000)) {
+            printfd(__FILE__, "CONFIG_THREAD::SendData() Failed to write data block\n");
+            return;
+        }
+
+        pos += size; // size?
+    }
+
+    return;
+}
+
+bool CONFIG_THREAD::CheckLogin(const std::string & login, std::string & password)
+{
+    currAdmin = admins->FindAdmin(login);
+
+    if (currAdmin == NULL) {
+        printfd(__FILE__, "CONFIG_THREAD::CheckLogin() Admin '%s' not found\n", login.c_str());
+        return false;
+    }
+
+    password = currAdmin->GetPassword();
+
+    return true;
+}
+
+void CONFIG_THREAD::TagBegin(void * userData, const char * name, const char ** attr)
+{
+    ROOT_PARSER * self = static_cast<ROOT_PARSER *>(userData);
+    self->StartTag(name, attr);
+}
+
+void CONFIG_THREAD::TagEnd(void * userData, const char * name)
+{
+    ROOT_PARSER * self = static_cast<ROOT_PARSER *>(userData);
+    self->EndTag(name);
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/config_thread.h b/projects/stargazer/plugins/configuration/sgconfig-ng/config_thread.h
new file mode 100644 (file)
index 0000000..1e6742b
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef __CONFIG_THREAD_H__
+#define __CONFIG_THREAD_H__
+
+#include <arpa/inet.h>
+#include <openssl/blowfish.h>
+
+class ADMINS;
+class ADMIN;
+class TARIFFS;
+class USERS;
+class SETTINGS;
+
+namespace boost {
+    class mutex;
+};
+
+class CONFIG_THREAD {
+public:
+    CONFIG_THREAD(ADMINS * , TARIFFS * t, USERS * u, const SETTINGS * s);
+    CONFIG_THREAD(const CONFIG_THREAD & rvalue);
+    ~CONFIG_THREAD();
+
+
+    void operator() ();
+
+    void SetConnection(int sock, struct sockaddr_in sin);
+    bool IsDone() const;
+
+    enum {ST_NOOP, ST_OK, ST_ERROR};
+
+private:
+    int sd;
+    struct sockaddr_in remoteAddr;
+    bool done;
+    int state;
+    uint16_t versionMinor;
+    uint16_t versionMajor;
+    std::string message;
+    std::string login;
+    std::string password;
+    std::string xml;
+    uint32_t respCode;
+
+    BF_KEY key;
+    unsigned char * iv;
+
+    ADMINS * admins;
+    TARIFFS * tariffs;
+    USERS * users;
+    const SETTINGS * settings;
+    const ADMIN * currAdmin;
+
+    mutable boost::mutex mutex;
+
+    bool ReadBlock(void * dest, size_t & size, int timeout) const;
+    bool WriteBlock(const void * source, size_t & size, int timeout) const;
+
+    bool ReadReq();
+    void Process();
+    void WriteResp() const;
+    //void MakeErrorXML();
+
+    bool CheckLogin(const std::string & login, std::string & password);
+    bool ReceiveData();
+    void SendData() const;
+
+    static void TagBegin(void * userData, const char * name, const char ** attr);
+    static void TagEnd(void * userData, const char * name);
+
+
+    CONFIG_THREAD & operator=(const CONFIG_THREAD & rvalue);
+};
+
+#endif
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/creator.cpp b/projects/stargazer/plugins/configuration/sgconfig-ng/creator.cpp
new file mode 100644 (file)
index 0000000..042c205
--- /dev/null
@@ -0,0 +1,29 @@
+#include "stgconfig.h"
+
+class STGCONFIG_CREATOR
+{
+private:
+    STGCONFIG2 * stgconfig;
+
+public:
+    STGCONFIG_CREATOR()
+        : stgconfig(new STGCONFIG2())
+        {
+        };
+    ~STGCONFIG_CREATOR()
+        {
+        delete stgconfig;
+        };
+
+    STGCONFIG2 * GetPlugin()
+        {
+        return stgconfig;
+        };
+};
+
+STGCONFIG_CREATOR stgc;
+
+BASE_PLUGIN * GetPlugin()
+{
+return stgc.GetPlugin();
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/main_thread.cpp b/projects/stargazer/plugins/configuration/sgconfig-ng/main_thread.cpp
new file mode 100644 (file)
index 0000000..013cf20
--- /dev/null
@@ -0,0 +1,139 @@
+#include <unistd.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <cerrno>
+#include <cstring>
+
+#include <boost/thread.hpp>
+
+#include "common.h"
+
+#include "main_thread.h"
+#include "config_thread.h"
+
+MAIN_THREAD::MAIN_THREAD(ADMINS * a, TARIFFS * t, USERS * u, const SETTINGS * s)
+    : running(true),
+      sd(-1),
+      port(44000),
+      maxConnections(60),
+      admins(a),
+      tariffs(t),
+      users(u),
+      settings(s)
+{
+}
+
+MAIN_THREAD::~MAIN_THREAD()
+{
+}
+
+void MAIN_THREAD::operator() ()
+{
+    if (!InitNetwork()) {
+        return;
+    }
+
+    int counter = 0;
+    while (running) {
+        if (WaitConnection()) {
+            AcceptConnection();
+        }
+        if (counter == 0) {
+            CleanupThreads();
+        }
+        ++counter;
+        counter = counter % 10; // Every 5 sec
+    }
+
+    close(sd);
+}
+
+bool MAIN_THREAD::InitNetwork()
+{
+    struct sockaddr_in listenAddr;
+
+    sd = socket(AF_INET, SOCK_STREAM, 0);
+
+    if (sd < 0) {
+        printfd(__FILE__, "MAIN_THREAD::InitNetwork() Socket creation failed: '%s'\n", strerror(errno));
+        return false;
+    }
+
+    listenAddr.sin_family = AF_INET;
+    listenAddr.sin_port = htons(port);
+    listenAddr.sin_addr.s_addr = INADDR_ANY;
+
+    if (bind(sd, (struct sockaddr*)&listenAddr, sizeof(listenAddr)) < 0) {
+        printfd(__FILE__, "MAIN_THREAD::InitNetwork() Bind failed: '%s'\n", strerror(errno));
+        return false;
+    }
+
+    if(listen(sd, 8) < 0) {
+        printfd(__FILE__, "MAIN_THREAD::InitNetwork() Error starting to listen: '%s'\n", strerror(errno));
+        return false;
+    }
+
+    return true;
+}
+
+bool MAIN_THREAD::WaitConnection()
+{
+    fd_set rfds;
+    FD_ZERO(&rfds);
+    FD_SET(sd, &rfds);
+
+    /* Wait up to five seconds. */
+    struct timeval tv;
+    tv.tv_sec = 1;
+    tv.tv_usec = 0;
+
+    int res = select(sd + 1, &rfds, NULL, NULL, &tv);
+    /* Don't rely on the value of tv now! */
+
+    if (res == -1) {
+        printfd(__FILE__, "MAIN_THREAD::WaitConnection() Select failed: '%s'\n", strerror(errno));
+        return false;
+    }
+
+    if (res && FD_ISSET(sd, &rfds)) {
+        return true;
+    }
+
+    // Timeout
+    return false;
+}
+
+void MAIN_THREAD::AcceptConnection()
+{
+    if (connections.size() >= maxConnections) {
+        CleanupThreads();
+        if (connections.size() >= maxConnections) {
+            return;
+        }
+    }
+
+    struct sockaddr_in remoteAddr;
+    socklen_t len = sizeof(remoteAddr);
+    int newSD = accept(sd, (struct sockaddr *)&remoteAddr, &len);
+
+    if (newSD < 0) {
+        printfd(__FILE__, "MAIN_THREAD::AcceptConnection() Accept failed: '%s'\n", strerror(errno));
+        return;
+    }
+
+    CONFIG_THREAD ct(admins, tariffs, users, settings);
+    ct.SetConnection(newSD, remoteAddr);
+
+    connections.push_back(ct);
+    boost::thread thread(boost::ref(connections.back()));
+    thread.detach();
+}
+
+void MAIN_THREAD::CleanupThreads()
+{
+    connections.remove_if(
+            std::mem_fun_ref(&CONFIG_THREAD::IsDone)
+            );
+    printfd(__FILE__, "MAIN_THREAD::CleanupThreads() Active threads: %d\n", connections.size());
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/main_thread.h b/projects/stargazer/plugins/configuration/sgconfig-ng/main_thread.h
new file mode 100644 (file)
index 0000000..d3ec96c
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __MAIN_THREAD_H__
+#define __MAIN_THREAD_H__
+
+#include <list>
+
+#include "os_int.h"
+
+class CONFIG_THREAD;
+class ADMINS;
+class TARIFFS;
+class USERS;
+class SETTINGS;
+
+class MAIN_THREAD {
+public:
+    MAIN_THREAD(ADMINS * a, TARIFFS * t, USERS * u, const SETTINGS * s);
+    ~MAIN_THREAD();
+
+    void operator() ();
+
+    void Stop() { running = false; };
+    void SetPort(uint16_t p) { port = p; };
+    void SetClasses(ADMINS * a,
+                    TARIFFS * t,
+                    USERS * u,
+                    const SETTINGS * s)
+    {
+        admins = a;
+        tariffs = t;
+        users = u;
+        settings = s;
+    };
+
+    void SetMaxConnections(unsigned max) { maxConnections = max; };
+
+private:
+    bool running;
+    int sd;
+    uint16_t port;
+    unsigned maxConnections;
+
+    ADMINS * admins;
+    TARIFFS * tariffs;
+    USERS * users;
+    const SETTINGS * settings;
+
+    std::list<CONFIG_THREAD> connections;
+
+    bool InitNetwork();
+    bool WaitConnection();
+    void AcceptConnection();
+    void CleanupThreads();
+
+};
+
+#endif
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/parser.h b/projects/stargazer/plugins/configuration/sgconfig-ng/parser.h
new file mode 100644 (file)
index 0000000..7f94958
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __PARSER_H__
+#define __PARSER_H__
+
+#include <string>
+
+class PARSER {
+    public:
+        PARSER() {};
+        virtual ~PARSER() {};
+
+        virtual bool StartTag(const char * name, const char ** attr) = 0;
+        virtual bool EndTag(const char * name) = 0;
+        virtual const std::string & GetResult() const = 0;
+};
+
+#endif
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getuser.cpp b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getuser.cpp
new file mode 100644 (file)
index 0000000..3b6a1cc
--- /dev/null
@@ -0,0 +1,130 @@
+// TODO: Fix this shit!
+#include "../../../admin.h"
+#include "../../../users.h"
+
+#include "parser_getuser.h"
+
+PARSER_GET_USER::PARSER_GET_USER(const ADMIN * ca, const USERS * u)
+    : PARSER(),
+      result("<error message=\"Not implemented yet\"/>"),
+      currAdmin(ca),
+      users(u)
+{
+}
+
+PARSER_GET_USER::~PARSER_GET_USER()
+{
+}
+
+bool PARSER_GET_USER::StartTag(const char * name, const char ** attr)
+{
+    std::string tag(name);
+    if (tag != "GetUser") {
+        return false;
+    }
+
+    if (attr[0] == NULL || attr[1] == NULL) {
+        return false;
+    }
+
+    login = attr[1];
+
+    return true;
+}
+
+bool PARSER_GET_USER::EndTag(const char * name)
+{
+    std::string tag(name);
+    if (tag != "GetUser") {
+        return false;
+    }
+
+    if (login == "") {
+        result = "<error message=\"Login unspecified\"/>";
+        return false;
+    }
+
+    user_iter ui;
+
+    if (users->FindByName(login, &ui)) {
+        result ="<error message=\"User not found\"/>";
+        return false;
+    }
+
+    std::stringstream answer;
+    answer << "<User>\n";
+    answer << "\t<login value=\"" << ui->GetLogin() << "\"/>\n";
+    if (currAdmin->GetPriv()->userConf || currAdmin->GetPriv()->userPasswd) {
+        answer << "\t<password value=\"" << ui->property.password.Get() << "\"/>\n";
+    } else {
+        answer << "\t<password value=\"++++++++\"/>\n";
+    }
+    answer << "\t<cash value=\"" << ui->property.cash.Get() << "\"/>\n";
+    answer << "\t<freemb value=\"" << ui->property.freeMb.Get() << "\"/>\n";
+    answer << "\t<credit value=\"" << ui->property.credit.Get() << "\"/>\n";
+    if (ui->property.nextTariff.Get() != "") {
+        answer << "\t<tariff value=\"" << ui->property.tariffName.Get()
+               << "/" << ui->property.nextTariff.Get() << "\"/>\n";
+    } else {
+        answer << "\t<tariff value=\"" << ui->property.tariffName.Get() << "\"/>\n";
+    }
+
+    std::string encoded;
+    Encode12str(encoded, ui->property.note.Get());
+    answer << "\t<note value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.phone.Get());
+    answer << "\t<phone value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.address.Get());
+    answer << "\t<address value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.email.Get());
+    answer << "\t<email value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.realName.Get());
+    answer << "\t<name value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.group.Get());
+    answer << "\t<group value=\"" << encoded << "\"/>\n";
+
+    // TODO: Fix this shit!
+    // <SHIT_BEGIN>
+    Encode12str(encoded, ui->property.userdata0.Get()); answer << "\t<userdata0 value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.userdata1.Get()); answer << "\t<userdata1 value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.userdata2.Get()); answer << "\t<userdata2 value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.userdata3.Get()); answer << "\t<userdata3 value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.userdata4.Get()); answer << "\t<userdata4 value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.userdata5.Get()); answer << "\t<userdata5 value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.userdata6.Get()); answer << "\t<userdata6 value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.userdata7.Get()); answer << "\t<userdata7 value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.userdata8.Get()); answer << "\t<userdata8 value=\"" << encoded << "\"/>\n";
+    Encode12str(encoded, ui->property.userdata9.Get()); answer << "\t<userdata9 value=\"" << encoded << "\"/>\n";
+    // <SHIT_END>
+
+    answer << "\t<status value=\"" << ui->GetConnected() << "\"/>\n";
+    answer << "\t<aonline value=\"" << ui->property.alwaysOnline.Get() << "\"/>\n";
+    answer << "\t<currip value=\"" << inet_ntostring(ui->GetCurrIP()) << "\"/>\n";
+    answer << "\t<pingtime value=\"" << ui->GetPingTime() << "\"/>\n";
+    answer << "\t<ip value=\"" << ui->property.ips.Get() << "\"/>\n";
+    answer << "\t<lastcash value=\"" << ui->property.lastCashAdd.Get() << "\"/>\n";
+    answer << "\t<lasttimecash value=\"" << ui->property.lastCashAddTime.Get() << "\"/>\n";
+    answer << "\t<lastactivitytime value=\"" << ui->property.lastActivityTime.Get() << "\"/>\n";
+    answer << "\t<creditexpire value=\"" << ui->property.creditExpire.Get() << "\"/>\n";
+    answer << "\t<down value=\"" << ui->property.down.Get() << "\"/>\n";
+    answer << "\t<passive value=\"" << ui->property.passive.Get() << "\"/>\n";
+    answer << "\t<disabledetailstat value=\"" << ui->property.disabledDetailStat.Get() << "\"/>\n";
+
+    // TODO: Fix this shit!
+    // <SHIT_BEGIN>
+    answer << "\t<traff ";
+    DIR_TRAFF up(ui->property.up.Get());
+    DIR_TRAFF down(ui->property.down.Get());
+    for (int i = 0; i < DIR_NUM; ++i) {
+        answer << "MU" << i << "=\"" << up[i] << "\" ";
+        answer << "MD" << i << "=\"" << down[i] << "\" ";
+    }
+    answer << "/>\n";
+    // <SHIT_END>
+
+    answer << "</User>";
+
+    result = answer.str();
+
+    return true;
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getuser.h b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getuser.h
new file mode 100644 (file)
index 0000000..81b4037
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __PARSER_GET_USER_H__
+#define __PSRSER_GET_USER_H__
+
+#include <string>
+
+#include "parser.h"
+
+class ADMIN;
+class USERS;
+
+class PARSER_GET_USER : public PARSER {
+    public:
+        PARSER_GET_USER(const ADMIN * ca, const USERS * u);
+        ~PARSER_GET_USER();
+
+        bool StartTag(const char * name, const char ** attr);
+        bool EndTag(const char * name);
+        const std::string & GetResult() const { return result; };
+
+    private:
+        std::string result;
+        std::string login;
+        const ADMIN * currAdmin;
+        const USERS * users;
+};
+
+#endif
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getusers.cpp b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getusers.cpp
new file mode 100644 (file)
index 0000000..e289570
--- /dev/null
@@ -0,0 +1,135 @@
+// TODO: Fix this shit!
+#include "../../../admin.h"
+#include "../../../users.h"
+
+#include "parser_getusers.h"
+
+PARSER_GET_USERS::PARSER_GET_USERS(const ADMIN * ca, USERS * u)
+    : PARSER(),
+      result("<error message=\"Not implemented yet\"/>"),
+      currAdmin(ca),
+      users(u)
+{
+}
+
+PARSER_GET_USERS::~PARSER_GET_USERS()
+{
+}
+
+bool PARSER_GET_USERS::StartTag(const char * name, const char ** attr)
+{
+    std::string tag(name);
+    if (tag != "GetUsers") {
+        return false;
+    }
+
+    return true;
+}
+
+bool PARSER_GET_USERS::EndTag(const char * name)
+{
+    std::string tag(name);
+    if (tag != "GetUsers") {
+        return false;
+    }
+
+    int handle = users->OpenSearch();
+    if (!handle) {
+        printfd(__FILE__, "PARSER_GET_USERS::EndTag() OpenSearch error\n");
+        users->CloseSearch(handle);
+        result = "<error message=\"Internal error (OpenSearch failed)\"/>";
+        return false;
+    }
+
+    std::stringstream answer;
+
+    answer << "<Users>\n";
+
+    while (1) {
+        user_iter ui;
+
+        if (users->SearchNext(handle, &ui)) {
+            break;
+        }
+
+        answer << "\t<User>\n";
+        answer << "\t\t<login value=\"" << ui->GetLogin() << "\"/>\n";
+        if (currAdmin->GetPriv()->userConf || currAdmin->GetPriv()->userPasswd) {
+            answer << "\t\t<password value=\"" << ui->property.password.Get() << "\"/>\n";
+        } else {
+            answer << "\t\t<password value=\"++++++++\"/>\n";
+        }
+        answer << "\t\t<cash value=\"" << ui->property.cash.Get() << "\"/>\n";
+        answer << "\t\t<freemb value=\"" << ui->property.freeMb.Get() << "\"/>\n";
+        answer << "\t\t<credit value=\"" << ui->property.credit.Get() << "\"/>\n";
+        if (ui->property.nextTariff.Get() != "") {
+            answer << "\t\t<tariff value=\"" << ui->property.tariffName.Get()
+                   << "/" << ui->property.nextTariff.Get() << "\"/>\n";
+        } else {
+            answer << "\t\t<tariff value=\"" << ui->property.tariffName.Get() << "\"/>\n";
+        }
+
+        std::string encoded;
+        Encode12str(encoded, ui->property.note.Get());
+        answer << "\t\t<note value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.phone.Get());
+        answer << "\t\t<phone value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.address.Get());
+        answer << "\t\t<address value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.email.Get());
+        answer << "\t\t<email value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.realName.Get());
+        answer << "\t\t<name value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.group.Get());
+        answer << "\t\t<group value=\"" << encoded << "\"/>\n";
+
+        // TODO: Fix this shit!
+        // <SHIT_BEGIN>
+        Encode12str(encoded, ui->property.userdata0.Get()); answer << "\t\t<userdata0 value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.userdata1.Get()); answer << "\t\t<userdata1 value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.userdata2.Get()); answer << "\t\t<userdata2 value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.userdata3.Get()); answer << "\t\t<userdata3 value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.userdata4.Get()); answer << "\t\t<userdata4 value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.userdata5.Get()); answer << "\t\t<userdata5 value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.userdata6.Get()); answer << "\t\t<userdata6 value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.userdata7.Get()); answer << "\t\t<userdata7 value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.userdata8.Get()); answer << "\t\t<userdata8 value=\"" << encoded << "\"/>\n";
+        Encode12str(encoded, ui->property.userdata9.Get()); answer << "\t\t<userdata9 value=\"" << encoded << "\"/>\n";
+        // <SHIT_END>
+
+        answer << "\t\t<status value=\"" << ui->GetConnected() << "\"/>\n";
+        answer << "\t\t<aonline value=\"" << ui->property.alwaysOnline.Get() << "\"/>\n";
+        answer << "\t\t<currip value=\"" << inet_ntostring(ui->GetCurrIP()) << "\"/>\n";
+        answer << "\t\t<pingtime value=\"" << ui->GetPingTime() << "\"/>\n";
+        answer << "\t\t<ip value=\"" << ui->property.ips.Get() << "\"/>\n";
+        answer << "\t\t<lastcash value=\"" << ui->property.lastCashAdd.Get() << "\"/>\n";
+        answer << "\t\t<lasttimecash value=\"" << ui->property.lastCashAddTime.Get() << "\"/>\n";
+        answer << "\t\t<lastactivitytime value=\"" << ui->property.lastActivityTime.Get() << "\"/>\n";
+        answer << "\t\t<creditexpire value=\"" << ui->property.creditExpire.Get() << "\"/>\n";
+        answer << "\t\t<down value=\"" << ui->property.disabled.Get() << "\"/>\n";
+        answer << "\t\t<passive value=\"" << ui->property.passive.Get() << "\"/>\n";
+        answer << "\t\t<disabledetailstat value=\"" << ui->property.disabledDetailStat.Get() << "\"/>\n";
+
+        // TODO: Fix this shit!
+        // <SHIT_BEGIN>
+        answer << "\t\t<traff ";
+        DIR_TRAFF up(ui->property.up.Get());
+        DIR_TRAFF down(ui->property.down.Get());
+        for (int i = 0; i < DIR_NUM; ++i) {
+            answer << "MU" << i << "=\"" << up[i] << "\" ";
+            answer << "MD" << i << "=\"" << down[i] << "\" ";
+        }
+        answer << "/>\n";
+        // <SHIT_END>
+
+        answer << "\t</User>\n";
+    }
+
+    answer << "</Users>";
+
+    users->CloseSearch(handle);
+
+    result = answer.str();
+
+    return true;
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getusers.h b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getusers.h
new file mode 100644 (file)
index 0000000..b0d37c5
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __PARSER_GET_USERS_H__
+#define __PSRSER_GET_USERS_H__
+
+#include <string>
+
+#include "parser.h"
+
+class ADMIN;
+class USERS;
+
+class PARSER_GET_USERS : public PARSER {
+    public:
+        PARSER_GET_USERS(const ADMIN * ca, USERS * u);
+        ~PARSER_GET_USERS();
+
+        bool StartTag(const char * name, const char ** attr);
+        bool EndTag(const char * name);
+        const std::string & GetResult() const { return result; };
+
+    private:
+        std::string result;
+        const ADMIN * currAdmin;
+        USERS * users;
+};
+
+#endif
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/parser_info.cpp b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_info.cpp
new file mode 100644 (file)
index 0000000..73fb667
--- /dev/null
@@ -0,0 +1,61 @@
+#include <sys/utsname.h>
+
+#include <sstream>
+
+#include "version.h"
+// TODO: Fix this shit!
+#include "../../../settings.h"
+#include "parser_info.h"
+
+PARSER_GET_SERVER_INFO::PARSER_GET_SERVER_INFO(const SETTINGS * s, int tn, int un)
+    : PARSER(),
+      result("<error message=\"Not implemented\"/>"),
+      settings(s),
+      tariffsNum(tn),
+      usersNum(un)
+{
+}
+
+PARSER_GET_SERVER_INFO::~PARSER_GET_SERVER_INFO()
+{
+}
+
+bool PARSER_GET_SERVER_INFO::StartTag(const char * name, const char ** attr)
+{
+    std::string tag(name);
+    if (tag != "GetServerInfo") {
+        return false;
+    }
+
+    return true;
+}
+
+bool PARSER_GET_SERVER_INFO::EndTag(const char * name)
+{
+    std::string tag(name);
+    if (tag != "GetServerInfo") {
+        return false;
+    }
+
+    std::stringstream answer;
+    answer << "<ServerInfo>\n";
+    answer << "\t<version value=\"" << SERVER_VERSION << "\"/>\n";
+    answer << "\t<tariff_num value=\"" << tariffsNum << "\"/>\n";
+    answer << "\t<tariff value=\"2\"/>\n";
+    answer << "\t<users_num value=\"" << usersNum << "\"/>\n";
+    struct utsname utsn;
+    uname(&utsn);
+    answer << "\t<uname value=\"" << utsn.sysname << " " << utsn.release << " " << utsn.machine << " " << utsn.nodename << "\"/>\n";
+    answer << "\t<dir_num value=\"" << DIR_NUM << "\"/>\n";
+    answer << "\t<day_fee value=\"" << settings->GetDayFee() << "\"/>\n";
+    for (int i = 0; i < DIR_NUM; ++i) {
+        std::string encoded;
+        Encode12str(encoded, settings->GetDirName(i));
+        answer << "\t<dir_name_" << i << " value=\"" << encoded << "\"/>\n";
+    }
+    answer << "</ServerInfo>";
+
+    result = answer.str();
+
+    return true;
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/parser_info.h b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_info.h
new file mode 100644 (file)
index 0000000..f45c86d
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __PARSER_INFO_H__
+#define __PARSER_INFO_H__
+
+#include "parser.h"
+
+class SETTINGS;
+
+class PARSER_GET_SERVER_INFO : public PARSER {
+    public:
+        PARSER_GET_SERVER_INFO(const SETTINGS * s, int tn, int un);
+        ~PARSER_GET_SERVER_INFO();
+
+        bool StartTag(const char * name, const char ** attr);
+        bool EndTag(const char * name);
+        const std::string & GetResult() const { return result; };
+
+    private:
+        std::string result;
+        const SETTINGS * settings;
+        int tariffsNum;
+        int usersNum;
+};
+
+#endif
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/proto.h b/projects/stargazer/plugins/configuration/sgconfig-ng/proto.h
new file mode 100644 (file)
index 0000000..183ab6c
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef __PROTO_H__
+#define __PROTO_H__
+
+#define PROTO_MAGIC "12345678"
+
+namespace REQ {
+    struct HEADER {
+        char magic[8];
+        uint32_t version;
+        char login[36];
+    };
+
+    struct CRYPTO_HEADER {
+        char login[36];
+        uint32_t dataSize;
+    };
+}
+
+namespace RESP {
+    enum {
+        OK = 0,
+        INVALID_MAGIC,
+        UNSUPPORTED_VERSION,
+        INVALID_CREDENTIALS
+    };
+
+    struct HEADER {
+        char magic[8];
+        uint32_t version;
+        uint32_t code;
+    };
+
+    struct CRYPTO_HEADER {
+        char login[36];
+        uint32_t dataSize;
+    };
+}
+
+#endif
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/root_parser.cpp b/projects/stargazer/plugins/configuration/sgconfig-ng/root_parser.cpp
new file mode 100644 (file)
index 0000000..8d32c85
--- /dev/null
@@ -0,0 +1,94 @@
+#include <cassert>
+
+#include "common.h"
+
+// TODO: Fix this shit!
+#include "../../../tariffs.h"
+#include "../../../users.h"
+#include "../../../admin.h"
+#include "../../../settings.h"
+
+#include "parser_info.h"
+#include "parser_getuser.h"
+#include "parser_getusers.h"
+#include "root_parser.h"
+
+ROOT_PARSER::ROOT_PARSER(const ADMIN * ca, TARIFFS * t, USERS * u, const SETTINGS * s)
+    : PARSER(),
+      tariffs(t),
+      users(u),
+      currAdmin(ca),
+      settings(s),
+      handler(NULL),
+      depth(0),
+      handlerResult("<error message=\"Not implemented yet\"/>")
+{
+    // new, new, new...
+    handlers["GetServerInfo"] = new PARSER_GET_SERVER_INFO(settings,
+                                          tariffs->GetTariffsNum(),
+                                          users->GetUserNum());
+    handlers["GetUser"] = new PARSER_GET_USER(currAdmin, users);
+    handlers["GetUsers"] = new PARSER_GET_USERS(currAdmin, users);
+}
+
+ROOT_PARSER::~ROOT_PARSER()
+{
+    std::map<std::string, PARSER *>::iterator it;
+
+    for (it = handlers.begin(); it != handlers.end(); ++it) {
+        delete it->second;
+    }
+}
+
+bool ROOT_PARSER::StartTag(const char * name, const char ** attr)
+{
+    if (depth == 0) {
+        handlerResult = "<error message=\"Not implemented yet\"/>";
+        Dispatch(name);
+    }
+
+    ++depth;
+
+    //assert(handler != NULL);
+
+    if (handler != NULL)
+        return handler->StartTag(name, attr);
+    else
+        return false;
+}
+
+bool ROOT_PARSER::EndTag(const char * name)
+{
+    assert(depth > 0);
+
+    bool res;
+    if (handler != NULL)
+       res = handler->EndTag(name);
+    else
+       res = false;
+
+    --depth;
+
+    if (depth == 0) {
+        if (handler != NULL) {
+            handlerResult = handler->GetResult();
+        }
+        handler = NULL;
+    }
+
+    return res;
+}
+
+bool ROOT_PARSER::Dispatch(const std::string & name)
+{
+    HMAP_ITERATOR it(handlers.find(name));
+
+    if (it == handlers.end()) {
+        printfd(__FILE__, "ROOT_PARSER::Dispatch() Handler for '%s' not found.\n", name.c_str());
+        return false;
+    }
+
+    handler = it->second;
+
+    return true;
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/root_parser.h b/projects/stargazer/plugins/configuration/sgconfig-ng/root_parser.h
new file mode 100644 (file)
index 0000000..8d722e8
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __ROOT_PARSER_H__
+#define __ROOT_PARSER_H__
+
+#include <map>
+#include <string>
+
+#include "parser.h"
+
+class TARIFFS;
+class USERS;
+class ADMIN;
+class SETTINGS;
+
+class ROOT_PARSER : public PARSER {
+    public:
+        ROOT_PARSER(const ADMIN * ca, TARIFFS * t, USERS * u, const SETTINGS * s);
+        ~ROOT_PARSER();
+
+        bool StartTag(const char * name, const char ** attr);
+        bool EndTag(const char * name);
+        const std::string & GetResult() const { return handlerResult; };
+
+    private:
+        TARIFFS * tariffs;
+        USERS * users;
+        const ADMIN * currAdmin;
+        const SETTINGS * settings;
+
+        typedef std::map<std::string, PARSER *> HMAP;
+        typedef HMAP::iterator HMAP_ITERATOR;
+
+        HMAP handlers;
+        PARSER * handler;
+        int depth;
+        std::string handlerResult;
+
+        bool Dispatch(const std::string & name);
+};
+
+#endif
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/stgconfig.cpp b/projects/stargazer/plugins/configuration/sgconfig-ng/stgconfig.cpp
new file mode 100644 (file)
index 0000000..1b51bbc
--- /dev/null
@@ -0,0 +1,58 @@
+#include <boost/thread.hpp>
+
+#include "base_store.h"
+#include "base_settings.h"
+#include "common.h"
+
+// TODO: Fix this shit!!!
+#include "../../../users.h"
+#include "../../../tariffs.h"
+#include "../../../admins.h"
+#include "../../../settings.h"
+
+#include "stgconfig.h"
+
+STGCONFIG2::STGCONFIG2()
+    : users(NULL),
+      tariffs(NULL),
+      admins(NULL),
+      store(NULL),
+      stgSettings(NULL),
+      ct(admins, tariffs, users, stgSettings)
+{
+    thread = new boost::thread;
+}
+
+STGCONFIG2::~STGCONFIG2()
+{
+    delete thread;
+}
+
+int STGCONFIG2::ParseSettings()
+{
+    return 0;
+}
+
+int STGCONFIG2::Start()
+{
+    ct.SetClasses(admins, tariffs, users, stgSettings);
+    *thread = boost::thread(boost::ref(ct));
+    return 0;
+}
+
+int STGCONFIG2::Stop()
+{
+    ct.Stop();
+    if (!thread->timed_join(boost::get_system_time() + boost::posix_time::milliseconds(5000))) {
+        thread->detach();
+        printfd(__FILE__, "STGCONFIG2::Stop() Thread not stopped.\n");
+        errorStr = "Failed to stop config thread.";
+        return -1;
+    }
+    return 0;
+}
+
+bool STGCONFIG2::IsRunning()
+{
+    return true;
+}
diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/stgconfig.h b/projects/stargazer/plugins/configuration/sgconfig-ng/stgconfig.h
new file mode 100644 (file)
index 0000000..28e52d1
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __STGCONFIG_H__
+#define __STGCONFIG_H__
+
+#include <string>
+
+#include "base_plugin.h"
+#include "os_int.h"
+#include "main_thread.h"
+
+#define PLUGIN_VERSION "stgconfig v.2.0"
+
+namespace boost {
+    class thread;
+};
+
+class USERS;
+class TARIFFS;
+class ADMINS;
+class BASE_STORE;
+class TRAFFCOUNTER;
+class SETTINGS;
+
+class STGCONFIG2 : public BASE_PLUGIN
+{
+public:
+    STGCONFIG2();
+    virtual ~STGCONFIG2();
+
+    void                SetUsers(USERS * u) { users = u; };
+    void                SetTariffs(TARIFFS * t) { tariffs = t; };
+    void                SetAdmins(ADMINS * a) { admins = a; };
+    void                SetStore(BASE_STORE * s) { store = s; };
+    void                SetTraffcounter(TRAFFCOUNTER *) {};
+    void                SetStgSettings(const SETTINGS * s) { stgSettings = s; };
+    void                SetSettings(const MODULE_SETTINGS & s) { modSettings = s; };
+    int                 ParseSettings();
+
+    int                 Start();
+    int                 Stop();
+    int                 Reload() { return 0; };
+    bool                IsRunning();
+
+    const std::string & GetStrError() const { return errorStr; };
+    const std::string   GetVersion() const { return PLUGIN_VERSION; };
+    uint16_t            GetStartPosition() const { return 220; };
+    uint16_t            GetStopPosition() const { return 220; };
+
+private:
+    USERS * users;
+    TARIFFS * tariffs;
+    ADMINS * admins;
+    BASE_STORE * store;
+    const SETTINGS * stgSettings;
+    MODULE_SETTINGS modSettings;
+
+    MAIN_THREAD ct;
+
+    mutable std::string errorStr;
+
+    boost::thread * thread;
+
+};
+
+extern "C" BASE_PLUGIN * GetPlugin();
+
+#endif