#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()); }