X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/b46ee6da376a4dc717ce2a2c68c0f59ae8225b1b..ebf7574cf9ee065013517c074fc0d8fd8053fabd:/projects/stargazer/plugins/configuration/sgconfig/configproto.cpp diff --git a/projects/stargazer/plugins/configuration/sgconfig/configproto.cpp b/projects/stargazer/plugins/configuration/sgconfig/configproto.cpp index fabeb54a..f7cd220e 100644 --- a/projects/stargazer/plugins/configuration/sgconfig/configproto.cpp +++ b/projects/stargazer/plugins/configuration/sgconfig/configproto.cpp @@ -23,11 +23,20 @@ #include "conn.h" +#include "parser_server_info.h" +#include "parser_admins.h" +#include "parser_tariffs.h" +#include "parser_users.h" +#include "parser_message.h" +#include "parser_user_info.h" +#include "parser_auth_by.h" + #include "stg/common.h" #include "stg/logger.h" #include #include +#include #include #include #include @@ -36,28 +45,9 @@ #include #include #include -#include - -namespace -{ - -struct IsFinished : public std::unary_function -{ - result_type operator()(const argument_type & arg) - { - return (arg->IsDone() && !arg->IsKeepAlive()) || !arg->IsOk(); - } -}; - -struct RemoveConn : public std::unary_function -{ - result_type operator()(const argument_type & arg) - { - delete arg; - } -}; +#include -} +namespace SP = STG::PARSER; CONFIGPROTO::CONFIGPROTO(PLUGIN_LOGGER & l) : m_settings(NULL), @@ -65,12 +55,19 @@ CONFIGPROTO::CONFIGPROTO(PLUGIN_LOGGER & l) m_tariffs(NULL), m_users(NULL), m_port(0), + m_bindAddress("0.0.0.0"), m_running(false), m_stopped(true), m_logger(l), m_listenSocket(-1) { - std::for_each(m_conns.begin(), m_conns.end(), RemoveConn()); +} + +CONFIGPROTO::~CONFIGPROTO() +{ + std::deque::iterator it; + for (it = m_conns.begin(); it != m_conns.end(); ++it) + delete *it; } int CONFIGPROTO::Prepare() @@ -92,11 +89,6 @@ int CONFIGPROTO::Prepare() return -1; } - struct sockaddr_in listenAddr; - listenAddr.sin_family = PF_INET; - listenAddr.sin_port = htons(m_port); - listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0"); // TODO: arbitrary address - int dummy = 1; if (setsockopt(m_listenSocket, SOL_SOCKET, SO_REUSEADDR, &dummy, 4) != 0) @@ -106,12 +98,8 @@ int CONFIGPROTO::Prepare() return -1; } - if (bind(m_listenSocket, reinterpret_cast(&listenAddr), sizeof(listenAddr)) == -1) - { - m_errorStr = std::string("Cannot bind listen socket: '") + strerror(errno) + "'."; - m_logger(m_errorStr); + if (!Bind()) return -1; - } if (listen(m_listenSocket, 64) == -1) // TODO: backlog length { @@ -120,6 +108,8 @@ int CONFIGPROTO::Prepare() return -1; } + RegisterParsers(); + m_running = true; m_stopped = false; return 0; @@ -162,42 +152,128 @@ void CONFIGPROTO::Run() if (res < 0) { m_errorStr = std::string("'select' is failed: '") + strerror(errno) + "'."; + printfd(__FILE__, "%s\n", m_errorStr.c_str()); m_logger(m_errorStr); break; } if (!m_running) break; if (res > 0) + { + printfd(__FILE__, "Something happend - received %d events.\n", res); HandleEvents(fds); + } CleanupConns(); } m_stopped = true; } +bool CONFIGPROTO::Bind() +{ + const hostent * he = gethostbyname(m_bindAddress.c_str()); + if (he == NULL) + { + m_errorStr = "Failed to resolve name '" + m_bindAddress + "': '" + hstrerror(h_errno) + "'."; + printfd(__FILE__, "%s\n", m_errorStr.c_str()); + m_logger(m_errorStr); + return false; + } + + char ** ptr = he->h_addr_list; + while (*ptr != NULL) + { + struct sockaddr_in listenAddr; + listenAddr.sin_family = PF_INET; + listenAddr.sin_port = htons(m_port); + listenAddr.sin_addr.s_addr = *reinterpret_cast(*ptr); + + printfd(__FILE__, "Trying to bind to %s:%d\n", inet_ntostring(listenAddr.sin_addr.s_addr).c_str(), m_port); + + if (bind(m_listenSocket, reinterpret_cast(&listenAddr), sizeof(listenAddr)) == 0) + return true; + + m_errorStr = std::string("Cannot bind listen socket: '") + strerror(errno) + "'."; + printfd(__FILE__, "%s\n", m_errorStr.c_str()); + m_logger(m_errorStr); + + ++ptr; + } + + return false; +} + +void CONFIGPROTO::RegisterParsers() +{ + assert(m_settings != NULL); + assert(m_store != NULL); + assert(m_admins != NULL); + assert(m_users != NULL); + assert(m_tariffs != NULL); + + SP::GET_SERVER_INFO::FACTORY::Register(m_registry, *m_settings, *m_users, *m_tariffs); + + SP::GET_ADMINS::FACTORY::Register(m_registry, *m_admins); + SP::ADD_ADMIN::FACTORY::Register(m_registry, *m_admins); + SP::DEL_ADMIN::FACTORY::Register(m_registry, *m_admins); + SP::CHG_ADMIN::FACTORY::Register(m_registry, *m_admins); + + SP::GET_TARIFFS::FACTORY::Register(m_registry, *m_tariffs); + SP::ADD_TARIFF::FACTORY::Register(m_registry, *m_tariffs); + SP::DEL_TARIFF::FACTORY::Register(m_registry, *m_tariffs, *m_users); + SP::CHG_TARIFF::FACTORY::Register(m_registry, *m_tariffs); + + SP::GET_USERS::FACTORY::Register(m_registry, *m_users); + SP::GET_USER::FACTORY::Register(m_registry, *m_users); + SP::ADD_USER::FACTORY::Register(m_registry, *m_users); + SP::DEL_USER::FACTORY::Register(m_registry, *m_users); + SP::CHG_USER::FACTORY::Register(m_registry, *m_users, *m_store, *m_tariffs); + SP::CHECK_USER::FACTORY::Register(m_registry, *m_users); + + SP::SEND_MESSAGE::FACTORY::Register(m_registry, *m_users); + + SP::AUTH_BY::FACTORY::Register(m_registry, *m_users); + + SP::USER_INFO::FACTORY::Register(m_registry, *m_users); +} + int CONFIGPROTO::MaxFD() const { int maxFD = m_listenSocket; - for (size_t i = 0; i < m_conns.size(); ++i) - if (maxFD < m_conns[i]->Sock()) - maxFD = m_conns[i]->Sock(); + std::deque::const_iterator it; + for (it = m_conns.begin(); it != m_conns.end(); ++it) + if (maxFD < (*it)->Sock()) + maxFD = (*it)->Sock(); return maxFD; } void CONFIGPROTO::BuildFDSet(fd_set & fds) const { - for (size_t i = 0; i < m_conns.size(); ++i) - FD_SET(m_conns[i]->Sock(), &fds); + printfd(__FILE__, "Building fd set for %d connections.\n", m_conns.size()); + FD_ZERO(&fds); + FD_SET(m_listenSocket, &fds); + std::deque::const_iterator it; + for (it = m_conns.begin(); it != m_conns.end(); ++it) + FD_SET((*it)->Sock(), &fds); } void CONFIGPROTO::CleanupConns() { - std::vector::iterator pos; - pos = std::remove_if(m_conns.begin(), m_conns.end(), IsFinished()); - if (pos == m_conns.end()) - return; - std::for_each(pos, m_conns.end(), RemoveConn()); + size_t old = m_conns.size(); + + std::deque::iterator pos; + for (pos = m_conns.begin(); pos != m_conns.end(); ++pos) + if (((*pos)->IsDone() && !(*pos)->IsKeepAlive()) || !(*pos)->IsOk()) + { + delete *pos; + *pos = NULL; + } + + pos = std::remove(m_conns.begin(), m_conns.end(), static_cast(NULL)); m_conns.erase(pos, m_conns.end()); + + if (m_conns.size() < old) + printfd(__FILE__, "Cleaned up %d connections.\n", old - m_conns.size()); } void CONFIGPROTO::HandleEvents(const fd_set & fds) @@ -206,14 +282,20 @@ void CONFIGPROTO::HandleEvents(const fd_set & fds) AcceptConnection(); else { - for (size_t i = 0; i < m_conns.size(); ++i) - if (FD_ISSET(m_conns[i]->Sock(), &fds)) - m_conns[i]->Read(); + std::deque::iterator it; + for (it = m_conns.begin(); it != m_conns.end(); ++it) + if (FD_ISSET((*it)->Sock(), &fds)) + { + printfd(__FILE__, "Reading data from %s:%d.\n", inet_ntostring((*it)->IP()).c_str(), (*it)->Port()); + (*it)->Read(); + } } } void CONFIGPROTO::AcceptConnection() { + printfd(__FILE__, "Accepting new connection.\n"); + struct sockaddr_in outerAddr; socklen_t outerAddrLen(sizeof(outerAddr)); int sock = accept(m_listenSocket, reinterpret_cast(&outerAddr), &outerAddrLen); @@ -221,20 +303,17 @@ void CONFIGPROTO::AcceptConnection() if (sock < 0) { m_errorStr = std::string("Failed to accept connection: '") + strerror(errno) + "'."; - printfd(__FILE__, "%s", m_errorStr.c_str()); + printfd(__FILE__, "%s\n", m_errorStr.c_str()); m_logger(m_errorStr); return; } - assert(m_settings != NULL); assert(m_admins != NULL); - assert(m_users != NULL); - assert(m_tariffs != NULL); try { - m_conns.push_back(new STG::Conn(*m_settings, *m_admins, *m_users, *m_tariffs, sock, outerAddr)); - printfd(__FILE__, "New connection from %s:%d\n", inet_ntostring(m_conns.back()->IP()).c_str(), m_conns.back()->Port()); + m_conns.push_back(new STG::Conn(m_registry, *m_admins, sock, outerAddr)); + printfd(__FILE__, "New connection from %s:%d. Total connections: %d\n", inet_ntostring(m_conns.back()->IP()).c_str(), m_conns.back()->Port(), m_conns.size()); } catch (const STG::Conn::Error & error) {