138 lines
4.2 KiB
C++
138 lines
4.2 KiB
C++
#include <algorithm>
|
|
#include <thread>
|
|
#include "src/TSServer.h"
|
|
#include "log/LogUtils.h"
|
|
#include "TeamSpeakWebClient.h"
|
|
#include "WebListManager.h"
|
|
|
|
using namespace std;
|
|
using namespace std::chrono;
|
|
using namespace ts;
|
|
using namespace ts::server;
|
|
using namespace ts::weblist;
|
|
|
|
WebListManager::WebListManager() {
|
|
this->event_base = event_base_new();
|
|
|
|
this->event_base_dispatch = std::thread([&](){
|
|
system_clock::time_point start;
|
|
while(this->event_base) {
|
|
start = system_clock::now();
|
|
::event_base_dispatch(this->event_base);
|
|
if(system_clock::now() - start < seconds(1))
|
|
this_thread::sleep_for(seconds(1));
|
|
}
|
|
});
|
|
}
|
|
WebListManager::~WebListManager() {
|
|
auto base = this->event_base;
|
|
this->event_base = nullptr;
|
|
event_base_loopbreak(base);
|
|
this->event_base_dispatch.join();
|
|
|
|
event_base_free(base);
|
|
}
|
|
|
|
void WebListManager::enable_report(const std::shared_ptr<ts::server::TSServer> &server) {
|
|
{
|
|
unique_lock lock(this->entry_lock);
|
|
for(const auto& entry : this->entries) {
|
|
if(entry->server == server)
|
|
return;
|
|
}
|
|
|
|
auto entry = make_shared<Entry>();
|
|
entry->server = server;
|
|
entry->scheduled_request = system_clock::now();
|
|
entry->fail_count = 0;
|
|
this->entries.push_back(entry);
|
|
}
|
|
}
|
|
|
|
bool WebListManager::reports_enabled(const std::shared_ptr<ts::server::TSServer> &server) {
|
|
{
|
|
lock_guard lock(this->entry_lock);
|
|
for(const auto& entry : this->entries) {
|
|
if(entry->server == server) return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void WebListManager::disable_report(const std::shared_ptr<ts::server::TSServer> &server) {
|
|
if(!server) return;
|
|
|
|
unique_lock lock(this->entry_lock);
|
|
for(const auto& entry : this->entries) {
|
|
if(entry->server == server) {
|
|
shared_ptr copied_entry = entry; //Copy it before erasing
|
|
|
|
auto it = find(this->entries.begin(), this->entries.end(), copied_entry);
|
|
if(it != this->entries.end())
|
|
this->entries.erase(it);
|
|
if(copied_entry->current_request) {
|
|
lock.unlock();
|
|
copied_entry->current_request->abort_sync();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void WebListManager::tick() {
|
|
if(!this->enabled) return;
|
|
|
|
unique_lock lock(this->entry_lock);
|
|
auto entries = this->entries;
|
|
lock.unlock();
|
|
|
|
auto now = system_clock::now();
|
|
for(const auto& entry : entries) {
|
|
if(entry->scheduled_request < now && (!entry->current_request || entry->scheduled_request + minutes(5) < now)) {
|
|
entry->current_request = make_shared<TSWebClient>(entry->server, this->event_base, entry->session_count, entry->last_name != entry->server->getDisplayName());
|
|
|
|
weak_ptr weak_entry = entry;
|
|
entry->current_request->callback_success = [weak_entry, now](){
|
|
auto _entry = weak_entry.lock();
|
|
if(!_entry) return;
|
|
|
|
_entry->fail_count = 0;
|
|
_entry->scheduled_request = now + minutes(10);
|
|
_entry->session_count++;
|
|
_entry->last_name = _entry->server->getDisplayName();
|
|
logMessage(_entry->server->getServerId(), "[WebList] Status update succeeded! Scheduling next update in ten minutes.");
|
|
|
|
_entry->current_request.reset();
|
|
};
|
|
entry->current_request->callback_error = [weak_entry, now](auto error, bool retry) {
|
|
auto _entry = weak_entry.lock();
|
|
if(!_entry) return;
|
|
|
|
_entry->fail_count++;
|
|
logError(_entry->server->getServerId(), "[WebList] Status update failed. Error: " + error);
|
|
|
|
if(_entry->fail_count == 1 && retry) {
|
|
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 5 seconds.");
|
|
_entry->scheduled_request = now + seconds(5);
|
|
} else if(_entry->fail_count == 2 && retry) {
|
|
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 30 seconds.");
|
|
_entry->scheduled_request = now + seconds(30);
|
|
} else if(_entry->fail_count == 3 && retry) {
|
|
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 1 minute.");
|
|
_entry->scheduled_request = now + seconds(60);
|
|
} else if(_entry->fail_count >= 4) {
|
|
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 10 minutes.");
|
|
_entry->scheduled_request = now + minutes(10);
|
|
}
|
|
|
|
_entry->current_request.reset();
|
|
};
|
|
|
|
{
|
|
/* could be blocking due to gethostbyname. We dont want to have the request deallocated */
|
|
auto ref_request = entry->current_request;
|
|
ref_request->report();
|
|
}
|
|
}
|
|
}
|
|
} |