#include #include #include #include #include #include "stg/plugin_creator.h" #include "stgconfig.h" #include "../../../tariffs.h" #include "../../../admins.h" #include "../../../users.h" PLUGIN_CREATOR stgc; BASE_PLUGIN * GetPlugin() { return stgc.GetPlugin(); } STG_CONFIG_SETTINGS::STG_CONFIG_SETTINGS() : port(0) { } const string& STG_CONFIG_SETTINGS::GetStrError() const { return errorStr; } int STG_CONFIG_SETTINGS::ParseSettings(const MODULE_SETTINGS & s) { int p; PARAM_VALUE pv; vector::const_iterator pvi; /////////////////////////// pv.param = "Port"; pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv); if (pvi == s.moduleParams.end()) { errorStr = "Parameter \'Port\' not found."; printfd(__FILE__, "Parameter 'Port' not found\n"); return -1; } if (ParseIntInRange(pvi->value[0], 2, 65535, &p)) { errorStr = "Cannot parse parameter \'Port\': " + errorStr; printfd(__FILE__, "%s\n", errorStr.c_str()); return -1; } port = p; return 0; } uint16_t STG_CONFIG_SETTINGS::GetPort() { return port; } STG_CONFIG::STG_CONFIG() : running(false), stopped(true) { } string STG_CONFIG::GetVersion() const { return "Stg configurator v.2.00"; } int STG_CONFIG::ParseSettings() { int ret = stgConfigSettings.ParseSettings(settings); if (ret) errorStr = stgConfigSettings.GetStrError(); return ret; } int STG_CONFIG::Start() { if (running) return false; if (PrepareNetwork()) return true; stopped = false; config.SetPort(stgConfigSettings.GetPort()); config.SetAdmins(admins); config.SetUsers(users); config.SetTariffs(tariffs); config.SetStgSettings(stgSettings); config.SetStore(store); if (config.Prepare()) { errorStr = config.GetStrError(); return true; } if (pthread_create(&thread, NULL, Run, this)) { errorStr = "Cannot create thread."; printfd(__FILE__, "Cannot create thread\n"); return true; } errorStr = ""; return false; } int STG_CONFIG::Stop() { if (!running) return false; running = false; config.Stop(); //5 seconds to thread stops itself int i; for (i = 0; i < 25 && !stopped; i++) { usleep(200000); } //after 5 seconds waiting thread still running. now killing it if (!stopped) { //TODO pthread_cancel() if (pthread_kill(thread, SIGINT)) { errorStr = "Cannot kill thread."; printfd(__FILE__, "Cannot kill thread\n"); return FinalizeNetwork(); } printfd(__FILE__, "STG_CONFIG killed\n"); } return FinalizeNetwork(); } void * STG_CONFIG::Run(void * d) { STG_CONFIG * stgConf = static_cast(d); stgConf->running = true; stgConf->RealRun(); stgConf->stopped = true; return NULL; } uint16_t STG_CONFIG::GetStartPosition() const { return 20; } uint16_t STG_CONFIG::GetStopPosition() const { return 20; } bool PrepareNetwork() { struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(port); local.sin_addr.s_addr = INADDR_ANY; sd = socket(AF_INET, SOCK_STREAM, 0); if (sd < 0) { errorStr = "Error creating socket: '"; errorStr += strerror(errno); errorStr += "'"; return true; } if (bind(sd, static_cast(&local), sizeof(local)) < 0) { errorStr = "Error binding socket: '"; errorStr += strerror(errno); errorStr += "'"; return true; } return false; } bool FinalizeNetwork() { if (close(sd) < 0) { errorStr = "Error closing socket: '"; errorStr += strerror(errno); errorStr += "'"; return true; } return false; } void STG_CONFIG::RealRun() { if (listen(sd, 64) < 0) { errorStr = "Error listening socket: '"; errorStr += strerror(errno); errorStr += "'"; return; } fd_set rfds; FD_ZERO(&rfds); FD_SET(sd, &rfds); running = true; while (running) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 500000; int res = select(sd + 1, &rfds, NULL, NULL, &tv); if (res < 0) { // Error logging } else if (res == 0) { // Timeout } else { if (FD_ISSET(sd, &rfds)) { AcceptConnection(); } } // Reorder: right part is done std::list::iterator done( std::remove_if( connections.begin(), connections.end(), std::not1(std::mem_fun(&ConnectionThread::isDone)) ) ); // Destruct done std::for_each( done, connections.end(), DeleteConnection()); // Erase done std::erase(done, connections.end()); } stopped = true; } void STG_CONFIG::AcceptConnection() { struct sockaddr_in remoteAddr; socklen_t len = sizeof(struct sockaddr_in); int rsd = accept(sd, &remoteAddr, &len); if (rsd < 0) { // Error logging } connections.push_back(new ConnectionThread(this, rsd, remoteAddr, users, admins, tariffs, store, stgSettings)); }