From: Maxim Mamontov Date: Mon, 8 Nov 2010 10:38:13 +0000 (+0200) Subject: Добавляю экспериментальный плагин конфигуратора. Проект полумертв, но X-Git-Tag: 2.407-rc3~376 X-Git-Url: https://git.stg.codes/stg.git/commitdiff_plain/9d093a68b5f3e5a22e243c92ec2e0bd24b10ea38 Добавляю экспериментальный плагин конфигуратора. Проект полумертв, но там есть интересные наработки. Так что пусть будет. --- diff --git a/projects/stargazer/plugins/configuration/sgconfig-ng/Makefile b/projects/stargazer/plugins/configuration/sgconfig-ng/Makefile new file mode 100644 index 00000000..13bf5484 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/Makefile @@ -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 index 00000000..38d6d859 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/config_thread.cpp @@ -0,0 +1,429 @@ +#include + +#include +#include +#include +#include + +#include + +// 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(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(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(password.c_str())); + + struct REQ::CRYPTO_HEADER reqCryptoHeader; + + BF_cbc_encrypt(buffer, reinterpret_cast(&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(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(&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(userData); + self->StartTag(name, attr); +} + +void CONFIG_THREAD::TagEnd(void * userData, const char * name) +{ + ROOT_PARSER * self = static_cast(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 index 00000000..1e6742b3 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/config_thread.h @@ -0,0 +1,74 @@ +#ifndef __CONFIG_THREAD_H__ +#define __CONFIG_THREAD_H__ + +#include +#include + +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 index 00000000..042c2055 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/creator.cpp @@ -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 index 00000000..013cf202 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/main_thread.cpp @@ -0,0 +1,139 @@ +#include +#include +#include + +#include +#include + +#include + +#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 index 00000000..d3ec96c0 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/main_thread.h @@ -0,0 +1,56 @@ +#ifndef __MAIN_THREAD_H__ +#define __MAIN_THREAD_H__ + +#include + +#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 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 index 00000000..7f949586 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/parser.h @@ -0,0 +1,16 @@ +#ifndef __PARSER_H__ +#define __PARSER_H__ + +#include + +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 index 00000000..3b6a1cc6 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getuser.cpp @@ -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(""), + 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 = ""; + return false; + } + + user_iter ui; + + if (users->FindByName(login, &ui)) { + result =""; + return false; + } + + std::stringstream answer; + answer << "\n"; + answer << "\tGetLogin() << "\"/>\n"; + if (currAdmin->GetPriv()->userConf || currAdmin->GetPriv()->userPasswd) { + answer << "\tproperty.password.Get() << "\"/>\n"; + } else { + answer << "\t\n"; + } + answer << "\tproperty.cash.Get() << "\"/>\n"; + answer << "\tproperty.freeMb.Get() << "\"/>\n"; + answer << "\tproperty.credit.Get() << "\"/>\n"; + if (ui->property.nextTariff.Get() != "") { + answer << "\tproperty.tariffName.Get() + << "/" << ui->property.nextTariff.Get() << "\"/>\n"; + } else { + answer << "\tproperty.tariffName.Get() << "\"/>\n"; + } + + std::string encoded; + Encode12str(encoded, ui->property.note.Get()); + answer << "\t\n"; + Encode12str(encoded, ui->property.phone.Get()); + answer << "\t\n"; + Encode12str(encoded, ui->property.address.Get()); + answer << "\t
\n"; + Encode12str(encoded, ui->property.email.Get()); + answer << "\t\n"; + Encode12str(encoded, ui->property.realName.Get()); + answer << "\t\n"; + Encode12str(encoded, ui->property.group.Get()); + answer << "\t\n"; + + // TODO: Fix this shit! + // + Encode12str(encoded, ui->property.userdata0.Get()); answer << "\t\n"; + Encode12str(encoded, ui->property.userdata1.Get()); answer << "\t\n"; + Encode12str(encoded, ui->property.userdata2.Get()); answer << "\t\n"; + Encode12str(encoded, ui->property.userdata3.Get()); answer << "\t\n"; + Encode12str(encoded, ui->property.userdata4.Get()); answer << "\t\n"; + Encode12str(encoded, ui->property.userdata5.Get()); answer << "\t\n"; + Encode12str(encoded, ui->property.userdata6.Get()); answer << "\t\n"; + Encode12str(encoded, ui->property.userdata7.Get()); answer << "\t\n"; + Encode12str(encoded, ui->property.userdata8.Get()); answer << "\t\n"; + Encode12str(encoded, ui->property.userdata9.Get()); answer << "\t\n"; + // + + answer << "\tGetConnected() << "\"/>\n"; + answer << "\tproperty.alwaysOnline.Get() << "\"/>\n"; + answer << "\tGetCurrIP()) << "\"/>\n"; + answer << "\tGetPingTime() << "\"/>\n"; + answer << "\tproperty.ips.Get() << "\"/>\n"; + answer << "\tproperty.lastCashAdd.Get() << "\"/>\n"; + answer << "\tproperty.lastCashAddTime.Get() << "\"/>\n"; + answer << "\tproperty.lastActivityTime.Get() << "\"/>\n"; + answer << "\tproperty.creditExpire.Get() << "\"/>\n"; + answer << "\tproperty.down.Get() << "\"/>\n"; + answer << "\tproperty.passive.Get() << "\"/>\n"; + answer << "\tproperty.disabledDetailStat.Get() << "\"/>\n"; + + // TODO: Fix this shit! + // + answer << "\tproperty.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"; + // + + answer << ""; + + 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 index 00000000..81b4037a --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getuser.h @@ -0,0 +1,27 @@ +#ifndef __PARSER_GET_USER_H__ +#define __PSRSER_GET_USER_H__ + +#include + +#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 index 00000000..e2895704 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getusers.cpp @@ -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(""), + 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 = ""; + return false; + } + + std::stringstream answer; + + answer << "\n"; + + while (1) { + user_iter ui; + + if (users->SearchNext(handle, &ui)) { + break; + } + + answer << "\t\n"; + answer << "\t\tGetLogin() << "\"/>\n"; + if (currAdmin->GetPriv()->userConf || currAdmin->GetPriv()->userPasswd) { + answer << "\t\tproperty.password.Get() << "\"/>\n"; + } else { + answer << "\t\t\n"; + } + answer << "\t\tproperty.cash.Get() << "\"/>\n"; + answer << "\t\tproperty.freeMb.Get() << "\"/>\n"; + answer << "\t\tproperty.credit.Get() << "\"/>\n"; + if (ui->property.nextTariff.Get() != "") { + answer << "\t\tproperty.tariffName.Get() + << "/" << ui->property.nextTariff.Get() << "\"/>\n"; + } else { + answer << "\t\tproperty.tariffName.Get() << "\"/>\n"; + } + + std::string encoded; + Encode12str(encoded, ui->property.note.Get()); + answer << "\t\t\n"; + Encode12str(encoded, ui->property.phone.Get()); + answer << "\t\t\n"; + Encode12str(encoded, ui->property.address.Get()); + answer << "\t\t
\n"; + Encode12str(encoded, ui->property.email.Get()); + answer << "\t\t\n"; + Encode12str(encoded, ui->property.realName.Get()); + answer << "\t\t\n"; + Encode12str(encoded, ui->property.group.Get()); + answer << "\t\t\n"; + + // TODO: Fix this shit! + // + Encode12str(encoded, ui->property.userdata0.Get()); answer << "\t\t\n"; + Encode12str(encoded, ui->property.userdata1.Get()); answer << "\t\t\n"; + Encode12str(encoded, ui->property.userdata2.Get()); answer << "\t\t\n"; + Encode12str(encoded, ui->property.userdata3.Get()); answer << "\t\t\n"; + Encode12str(encoded, ui->property.userdata4.Get()); answer << "\t\t\n"; + Encode12str(encoded, ui->property.userdata5.Get()); answer << "\t\t\n"; + Encode12str(encoded, ui->property.userdata6.Get()); answer << "\t\t\n"; + Encode12str(encoded, ui->property.userdata7.Get()); answer << "\t\t\n"; + Encode12str(encoded, ui->property.userdata8.Get()); answer << "\t\t\n"; + Encode12str(encoded, ui->property.userdata9.Get()); answer << "\t\t\n"; + // + + answer << "\t\tGetConnected() << "\"/>\n"; + answer << "\t\tproperty.alwaysOnline.Get() << "\"/>\n"; + answer << "\t\tGetCurrIP()) << "\"/>\n"; + answer << "\t\tGetPingTime() << "\"/>\n"; + answer << "\t\tproperty.ips.Get() << "\"/>\n"; + answer << "\t\tproperty.lastCashAdd.Get() << "\"/>\n"; + answer << "\t\tproperty.lastCashAddTime.Get() << "\"/>\n"; + answer << "\t\tproperty.lastActivityTime.Get() << "\"/>\n"; + answer << "\t\tproperty.creditExpire.Get() << "\"/>\n"; + answer << "\t\tproperty.disabled.Get() << "\"/>\n"; + answer << "\t\tproperty.passive.Get() << "\"/>\n"; + answer << "\t\tproperty.disabledDetailStat.Get() << "\"/>\n"; + + // TODO: Fix this shit! + // + answer << "\t\tproperty.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"; + // + + answer << "\t\n"; + } + + answer << ""; + + 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 index 00000000..b0d37c5e --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_getusers.h @@ -0,0 +1,26 @@ +#ifndef __PARSER_GET_USERS_H__ +#define __PSRSER_GET_USERS_H__ + +#include + +#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 index 00000000..73fb6679 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_info.cpp @@ -0,0 +1,61 @@ +#include + +#include + +#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(""), + 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 << "\n"; + answer << "\t\n"; + answer << "\t\n"; + answer << "\t\n"; + answer << "\t\n"; + struct utsname utsn; + uname(&utsn); + answer << "\t\n"; + answer << "\t\n"; + answer << "\tGetDayFee() << "\"/>\n"; + for (int i = 0; i < DIR_NUM; ++i) { + std::string encoded; + Encode12str(encoded, settings->GetDirName(i)); + answer << "\t\n"; + } + answer << ""; + + 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 index 00000000..f45c86d0 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/parser_info.h @@ -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 index 00000000..183ab6ca --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/proto.h @@ -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 index 00000000..8d32c85d --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/root_parser.cpp @@ -0,0 +1,94 @@ +#include + +#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("") +{ + // 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::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 = ""; + 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 index 00000000..8d722e87 --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/root_parser.h @@ -0,0 +1,40 @@ +#ifndef __ROOT_PARSER_H__ +#define __ROOT_PARSER_H__ + +#include +#include + +#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 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 index 00000000..1b51bbcb --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/stgconfig.cpp @@ -0,0 +1,58 @@ +#include + +#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 index 00000000..28e52d1c --- /dev/null +++ b/projects/stargazer/plugins/configuration/sgconfig-ng/stgconfig.h @@ -0,0 +1,66 @@ +#ifndef __STGCONFIG_H__ +#define __STGCONFIG_H__ + +#include + +#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