Removed the whole TS3 WebList feature
This commit is contained in:
parent
2c7e7e43d4
commit
1ea630b326
@ -88,7 +88,6 @@ namespace ts::server::file::transfer {
|
||||
} transfer_key{};
|
||||
|
||||
struct {
|
||||
/* TODO: Could be a spin lock (never gets locked while writing so no long blocking activity) */
|
||||
std::mutex mutex{};
|
||||
size_t bytes{0};
|
||||
|
||||
|
@ -125,9 +125,6 @@ set(SERVER_SOURCE_FILES
|
||||
src/ShutdownHelper.cpp
|
||||
src/lincense/TeamSpeakLicense.cpp
|
||||
|
||||
src/weblist/WebListManager.cpp
|
||||
src/weblist/TeamSpeakWebClient.cpp
|
||||
|
||||
src/snapshots/permission.cpp
|
||||
src/snapshots/client.cpp
|
||||
src/snapshots/channel.cpp
|
||||
|
@ -42,7 +42,6 @@ uint16_t ts::config::binding::DefaultFilePort;
|
||||
std::string config::server::DefaultServerVersion;
|
||||
std::string config::server::DefaultServerPlatform;
|
||||
LicenseType config::server::DefaultServerLicense;
|
||||
bool config::server::enable_teamspeak_weblist;
|
||||
bool config::server::strict_ut8_mode;
|
||||
bool config::server::show_invisible_clients_as_online;
|
||||
bool config::server::disable_ip_saving;
|
||||
@ -1283,11 +1282,6 @@ std::deque<std::shared_ptr<EntryBinding>> config::create_bindings() {
|
||||
ADD_DESCRIPTION("Enable/disable the deletion of invalid icon id permissions");
|
||||
}
|
||||
#endif
|
||||
{
|
||||
CREATE_BINDING("allow_weblist", 0);
|
||||
BIND_BOOL(config::server::enable_teamspeak_weblist, true);
|
||||
ADD_DESCRIPTION("Enable/disable weblist reports globally! (Server setting wount be disabled, they will be just not send)");
|
||||
}
|
||||
{
|
||||
CREATE_BINDING("strict_ut8_mode", FLAG_RELOADABLE);
|
||||
BIND_BOOL(config::server::strict_ut8_mode, false);
|
||||
|
@ -73,7 +73,6 @@ namespace ts::config {
|
||||
|
||||
extern bool strict_ut8_mode;
|
||||
|
||||
extern bool enable_teamspeak_weblist;
|
||||
extern bool show_invisible_clients_as_online;
|
||||
extern bool disable_ip_saving;
|
||||
extern bool default_music_bot;
|
||||
|
@ -3,7 +3,6 @@
|
||||
#define XFREE undefined_free
|
||||
#define XREALLOC undefined_realloc
|
||||
|
||||
#include "src/weblist/WebListManager.h"
|
||||
#include <log/LogUtils.h>
|
||||
#include "InstanceHandler.h"
|
||||
#include "src/client/InternalClient.h"
|
||||
@ -208,8 +207,6 @@ InstanceHandler::InstanceHandler(SqlDataManager *sql) : sql(sql) {
|
||||
|
||||
this->banMgr = new BanManager(this->getSql());
|
||||
this->banMgr->loadBans();
|
||||
|
||||
this->web_list = make_shared<weblist::WebListManager>();
|
||||
}
|
||||
|
||||
InstanceHandler::~InstanceHandler() {
|
||||
@ -256,8 +253,6 @@ bool InstanceHandler::startInstance() {
|
||||
|
||||
this->server_command_executor_ = std::make_shared<ServerCommandExecutor>(ts::config::threads::command_execute);
|
||||
|
||||
this->web_list->enabled = ts::config::server::enable_teamspeak_weblist;
|
||||
|
||||
this->permission_mapper = make_shared<permission::PermissionNameMapper>();
|
||||
if(!this->permission_mapper->initialize(config::permission_mapping_file, errorMessage)) {
|
||||
logCritical(LOG_INSTANCE, "Failed to initialize permission name mapping from file {}: {}", config::permission_mapping_file, errorMessage);
|
||||
@ -418,7 +413,6 @@ void InstanceHandler::stopInstance() {
|
||||
this->active = false;
|
||||
this->activeCon.notify_all();
|
||||
}
|
||||
this->web_list->enabled = false;
|
||||
this->server_command_executor_->shutdown();
|
||||
|
||||
/* TODO: Block on canceling. */
|
||||
@ -557,8 +551,6 @@ void InstanceHandler::tickInstance() {
|
||||
this->properties()[property::SERVERINSTANCE_SPOKEN_TIME_DELETED].as<uint64_t>() +
|
||||
this->properties()[property::SERVERINSTANCE_SPOKEN_TIME_VARIANZ].as<uint64_t>();
|
||||
}
|
||||
|
||||
this->web_list->tick();
|
||||
}
|
||||
|
||||
void InstanceHandler::save_group_permissions() {
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include <files/FileServer.h>
|
||||
|
||||
#include "weblist/WebListManager.h"
|
||||
#include "./client/web/WebClient.h"
|
||||
#include "./client/voice/VoiceClient.h"
|
||||
#include "./client/InternalClient.h"
|
||||
@ -516,9 +515,6 @@ bool VirtualServer::start(std::string& error) {
|
||||
}
|
||||
);
|
||||
|
||||
if(this->properties()[property::VIRTUALSERVER_WEBLIST_ENABLED].as<bool>())
|
||||
serverInstance->getWebList()->enable_report(this->self.lock());
|
||||
|
||||
properties()[property::VIRTUALSERVER_CLIENTS_ONLINE] = 0;
|
||||
properties()[property::VIRTUALSERVER_QUERYCLIENTS_ONLINE] = 0;
|
||||
properties()[property::VIRTUALSERVER_CHANNELS_ONLINE] = 0;
|
||||
@ -613,12 +609,6 @@ void VirtualServer::stop(const std::string& reason, bool disconnect_query) {
|
||||
this->webControlServer = nullptr;
|
||||
#endif
|
||||
|
||||
{
|
||||
auto list = serverInstance->getWebList();
|
||||
if(list)
|
||||
list->disable_report(self_lock);
|
||||
}
|
||||
|
||||
if(this->groups) {
|
||||
this->groups->clearCache();
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../server/QueryServer.h"
|
||||
#include "../../server/VoiceServer.h"
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../ConnectedClient.h"
|
||||
#include "../InternalClient.h"
|
||||
#include "../music/MusicClient.h"
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "../../server/QueryServer.h"
|
||||
#include "../music/MusicClient.h"
|
||||
#include "../query/QueryClient.h"
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "../../server/QueryServer.h"
|
||||
#include "../music/MusicClient.h"
|
||||
#include "../query/QueryClient.h"
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "../../server/QueryServer.h"
|
||||
#include "../music/MusicClient.h"
|
||||
#include "../query/QueryClient.h"
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "../../server/QueryServer.h"
|
||||
#include "../music/MusicClient.h"
|
||||
#include "../query/QueryClient.h"
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include <experimental/filesystem>
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "../../server/QueryServer.h"
|
||||
#include "../music/MusicClient.h"
|
||||
#include "../query/QueryClient.h"
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
@ -127,16 +126,7 @@ command_result ConnectedClient::handleCommandServerEdit(Command &cmd) {
|
||||
SERVEREDIT_CHK_PROP_CACHED("virtualserver_hostmessage_mode", permission::b_virtualserver_modify_hostmessage, int) }
|
||||
SERVEREDIT_CHK_PROP_CACHED("virtualserver_welcomemessage", permission::b_virtualserver_modify_welcomemessage, string) }
|
||||
|
||||
SERVEREDIT_CHK_PROP_CACHED("virtualserver_weblist_enabled", permission::b_virtualserver_modify_weblist, bool)
|
||||
if (target_server && target_server->running()) {
|
||||
if (cmd["virtualserver_weblist_enabled"].as<bool>())
|
||||
serverInstance->getWebList()->enable_report(target_server);
|
||||
else
|
||||
serverInstance->getWebList()->disable_report(target_server);
|
||||
debugMessage(target_server->getServerId(), "Changed weblist state to -> {}",
|
||||
cmd["virtualserver_weblist_enabled"].as<bool>() ? "activated" : "disabled");
|
||||
}
|
||||
} SERVEREDIT_CHK_PROP_CACHED("virtualserver_needed_identity_security_level", permission::b_virtualserver_modify_needed_identity_security_level, int) }
|
||||
SERVEREDIT_CHK_PROP_CACHED("virtualserver_needed_identity_security_level", permission::b_virtualserver_modify_needed_identity_security_level, int) }
|
||||
|
||||
SERVEREDIT_CHK_PROP_CACHED("virtualserver_antiflood_points_tick_reduce", permission::b_virtualserver_modify_antiflood, uint64_t) }
|
||||
SERVEREDIT_CHK_PROP_CACHED("virtualserver_antiflood_points_needed_command_block", permission::b_virtualserver_modify_antiflood, uint64_t) }
|
||||
|
@ -150,8 +150,10 @@ std::shared_ptr<IOEventLoop> VoiceIOManager::spawnEventLoop() {
|
||||
memset(thread_usage, 0, num_threads);
|
||||
|
||||
for(auto& ev_loop : this->event_loops) {
|
||||
if(ev_loop->bound_thread < 0 || ev_loop->bound_thread >= num_threads)
|
||||
if(ev_loop->bound_thread < 0 || ev_loop->bound_thread >= num_threads) {
|
||||
continue;
|
||||
}
|
||||
|
||||
thread_usage[ev_loop->bound_thread]++;
|
||||
}
|
||||
|
||||
|
@ -1,316 +0,0 @@
|
||||
#include "src/VirtualServer.h"
|
||||
#include "TeamSpeakWebClient.h"
|
||||
#include "log/LogUtils.h"
|
||||
#include "src/server/VoiceServer.h"
|
||||
|
||||
using namespace ts;
|
||||
using namespace ts::weblist;
|
||||
using namespace ts::server;
|
||||
|
||||
TSWebClient::TSWebClient(const std::shared_ptr<VirtualServer> &server, struct event_base *event_base, uint16_t session_index, bool resend_name) : server(server), event_base(event_base), session_index(session_index), send_name(resend_name) { }
|
||||
|
||||
TSWebClient::~TSWebClient() {
|
||||
this->unregister_events(true);
|
||||
try {
|
||||
if(this->close_thread.get_id() == std::this_thread::get_id())
|
||||
this->close_thread.detach();
|
||||
else if(this->close_thread.joinable())
|
||||
this->close_thread.join();
|
||||
} catch(std::exception& ex) {
|
||||
logCritical(this->server ? this->server->getServerId() : 0, "[WebList] Failed to join or detach close thread! message: {}", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
void TSWebClient::_handle_message_read(int file_descriptor, short, void *ptr_client) {
|
||||
const auto client = (TSWebClient*) ptr_client;
|
||||
|
||||
pipes::buffer buffer{512};
|
||||
const auto read = recv(file_descriptor, buffer.data_ptr(), buffer.length(), MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
if(read <= 0) {
|
||||
logError(client->server->getServerId(), "[WebList] Failed to read weblist response. ({} | {} => {})", read, errno, strerror(errno));
|
||||
|
||||
{
|
||||
std::lock_guard elock{client->event_mutex};
|
||||
if(client->event_read)
|
||||
event_del_noblock(client->event_read);
|
||||
}
|
||||
client->trigger_fail_later("failed to read!", true);
|
||||
return;
|
||||
}
|
||||
|
||||
client->handle_message_read(buffer.view(0, read));
|
||||
}
|
||||
|
||||
void TSWebClient::_handle_message_write(int file_descriptor, short, void *ptr_client) {
|
||||
const auto client = (TSWebClient*) ptr_client;
|
||||
pipes::buffer buffer;
|
||||
|
||||
{
|
||||
std::lock_guard lock(client->write_lock);
|
||||
if(client->write_buffer.empty()) return;
|
||||
buffer = std::move(client->write_buffer[0]);
|
||||
client->write_buffer.pop_front();
|
||||
|
||||
if(!client->write_buffer.empty()) {
|
||||
std::lock_guard elock{client->event_mutex};
|
||||
if(client->event_write)
|
||||
event_add(client->event_write, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
const auto write = sendto(file_descriptor, buffer.data_ptr(), buffer.length(), 0, (const sockaddr *) &client->remote_address, sizeof(sockaddr_in));
|
||||
if(write != buffer.length()){
|
||||
logError(client->server->getServerId(), "[WebList] Failed to send weblist response. ({} | {} => {})", write, errno, strerror(errno));
|
||||
client->trigger_fail_later("failed to write!", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void TSWebClient::_handle_timeout(int, short, void *ptr_client) {
|
||||
const auto client = (TSWebClient*) ptr_client;
|
||||
{
|
||||
std::lock_guard elock{client->event_mutex};
|
||||
if(client->event_timeout)
|
||||
event_del_noblock(client->event_timeout);
|
||||
}
|
||||
client->trigger_fail_later("timeout", true);
|
||||
}
|
||||
|
||||
void TSWebClient::unregister_events(bool blocking) {
|
||||
const auto unregister = [blocking](event*& event) {
|
||||
if(blocking) {
|
||||
event_del_block(event);
|
||||
event_free(event);
|
||||
event = nullptr;
|
||||
} else {
|
||||
event_del_noblock(event);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_lock elock{this->event_mutex};
|
||||
auto tevent = std::exchange(this->event_timeout, nullptr);
|
||||
auto revent = std::exchange(this->event_read, nullptr);
|
||||
auto wevent = std::exchange(this->event_write, nullptr);
|
||||
elock.unlock();
|
||||
|
||||
if(tevent) unregister(tevent);
|
||||
if(revent) unregister(revent);
|
||||
if(wevent) unregister(wevent);
|
||||
|
||||
if(this->file_descriptor > 0) {
|
||||
close(this->file_descriptor);
|
||||
this->file_descriptor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TSWebClient::reset_timeout(bool reschedule) {
|
||||
std::lock_guard elock{this->event_mutex};
|
||||
if(this->event_timeout) {
|
||||
event_del(this->event_timeout);
|
||||
if(reschedule) {
|
||||
timeval timeout{0};
|
||||
timeout.tv_sec = 5;
|
||||
event_add(this->event_timeout, &timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TSWebClient::trigger_fail_later(const std::string &error, bool retry) {
|
||||
if(this->state >= S_FINALIZING || this->close_thread.joinable()) return;
|
||||
this->state = S_FINALIZING;
|
||||
this->close_thread = std::thread([&, error, retry](){
|
||||
this->unregister_events(true);
|
||||
if(this->callback_error)
|
||||
this->callback_error(error,retry);
|
||||
});
|
||||
}
|
||||
|
||||
void TSWebClient::trigger_success_later() {
|
||||
if(this->state >= S_FINALIZING || this->close_thread.joinable()) return;
|
||||
this->state = S_FINALIZING;
|
||||
this->close_thread = std::thread([&](){
|
||||
this->unregister_events(true);
|
||||
if(this->callback_success)
|
||||
this->callback_success();
|
||||
});
|
||||
}
|
||||
|
||||
void TSWebClient::write_message(const pipes::buffer_view &buffer) {
|
||||
if(this->state >= S_FINALIZING) return;
|
||||
|
||||
{
|
||||
std::lock_guard lock(this->write_lock);
|
||||
this->write_buffer.push_back(buffer.own_buffer());
|
||||
}
|
||||
|
||||
if(this->event_write)
|
||||
event_add(this->event_write, nullptr);
|
||||
}
|
||||
|
||||
#define BASE_PORT 30566
|
||||
void TSWebClient::report() {
|
||||
this->state = S_INITIALIZING;
|
||||
|
||||
memset(&this->remote_address, 0, sizeof(sockaddr_in));
|
||||
this->remote_address.sin_family = AF_INET;
|
||||
this->remote_address.sin_port = htons(2010);
|
||||
{
|
||||
auto record = gethostbyname("weblist.teamspeak.com");
|
||||
if(!record) {
|
||||
this->trigger_fail_later("Failed to resolve weblist.teamspeak.com", true);
|
||||
return;
|
||||
}
|
||||
this->remote_address.sin_addr.s_addr = ((in_addr*) record->h_addr)->s_addr;
|
||||
}
|
||||
|
||||
|
||||
this->file_descriptor = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if(this->file_descriptor <= 0) {
|
||||
this->trigger_fail_later("Failed to create file descriptor", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if(fcntl(this->file_descriptor, F_SETFD, FD_CLOEXEC) < 0) {
|
||||
this->trigger_fail_later("Failed to enable FD_CLOEXEC for {} (WebReport)", true);
|
||||
return;
|
||||
}
|
||||
|
||||
int allow = 1;
|
||||
setsockopt(this->file_descriptor, SOL_SOCKET, SO_REUSEADDR, &allow, sizeof(int));
|
||||
|
||||
{
|
||||
sockaddr_in address{};
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(BASE_PORT + this->server->getServerId());
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if(this->server->getVoiceServer()) {
|
||||
for(const auto& binding : this->server->getVoiceServer()->activeBindings()) {
|
||||
if(binding->address.ss_family != AF_INET) continue;
|
||||
|
||||
address.sin_addr.s_addr = ((sockaddr_in*) &binding->address)->sin_addr.s_addr;
|
||||
debugMessage(this->server->getServerId(), "[WebList] Requesting from local address {}:{}", binding->address_string(), ntohs(address.sin_port));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(bind(this->file_descriptor, (const sockaddr *) &address, sizeof(address)) < 0) {
|
||||
this->trigger_fail_later("Failed to bind socket", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this->event_read = event_new(this->event_base, this->file_descriptor, EV_READ | EV_PERSIST, TSWebClient::_handle_message_read, this);
|
||||
this->event_write = event_new(this->event_base, this->file_descriptor, EV_WRITE, TSWebClient::_handle_message_write, this);
|
||||
this->event_timeout = event_new(this->event_base, -1, 0, TSWebClient::_handle_timeout, this);
|
||||
event_add(this->event_read, nullptr);
|
||||
|
||||
this->reset_timeout(true);
|
||||
this->request_session();
|
||||
}
|
||||
|
||||
void TSWebClient::abort() {
|
||||
this->trigger_fail_later("aborted", false);
|
||||
}
|
||||
|
||||
void TSWebClient::abort_sync() {
|
||||
this->unregister_events(true);
|
||||
if(this->callback_error)
|
||||
this->callback_error("aborted", false);
|
||||
}
|
||||
|
||||
inline char nibble(int c) {
|
||||
assert(c < 16);
|
||||
|
||||
if(c >= 0 && c <= 9)
|
||||
return (char) ('0' + c);
|
||||
else
|
||||
return (char) ('A' + (c - 10));
|
||||
}
|
||||
|
||||
inline std::string hex(const pipes::buffer_view &buffer) {
|
||||
std::string result;
|
||||
for(size_t index = 0; index < buffer.length(); index++)
|
||||
result += std::string() + "0x" + nibble(buffer[index] >> 4) + nibble(buffer[index] & 0x0F) + " ";
|
||||
|
||||
if(result.empty()) return result;
|
||||
return result.substr(0, result.length() - 1);
|
||||
}
|
||||
|
||||
void TSWebClient::handle_message_read(const pipes::buffer_view &buffer) {
|
||||
this->reset_timeout(true);
|
||||
if(this->state == S_INITIALIZING) {
|
||||
if(buffer.length() != 8) {
|
||||
this->trigger_fail_later("Failed to receive key. (Invalid packet length of " + std::to_string(buffer.length()) + ". Expected 8. Buffer: " + hex(buffer) + ")", true);
|
||||
return;
|
||||
}
|
||||
|
||||
this->session_id = *(uint32_t*) &buffer[4];
|
||||
this->send_status(this->send_name);
|
||||
} else if(this->state == S_DATA_EXCHANGE) {
|
||||
if(buffer.length() != 5) {
|
||||
this->trigger_fail_later("Failed to receive exchange stats. (Invalid packet length of " + std::to_string(buffer.length()) + ". Expected 5. Buffer: " + hex(buffer) + ")", true);
|
||||
return;
|
||||
}
|
||||
|
||||
int status = buffer[4];
|
||||
if(status == 7) {
|
||||
this->send_name = true;
|
||||
debugMessage(this->server->getServerId(), "[WebList] Received exchange status 7. Resending with server name.");
|
||||
this->send_status(true);
|
||||
return;
|
||||
} else if(status == 0) {
|
||||
this->trigger_success_later();
|
||||
return;
|
||||
} else {
|
||||
debugMessage(this->server->getServerId(), "[WebList] Weblist request failed. Status code {}. Buffer: {}", status, hex(buffer));
|
||||
this->trigger_fail_later("Invalid exchange status. Status: " + std::to_string(status), status != 5);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TSWebClient::request_session() {
|
||||
this->state = S_INITIALIZING;
|
||||
|
||||
pipes::buffer buffer{4};
|
||||
buffer[0] = 1; //Version
|
||||
buffer[1] = (uint8_t) (session_index >> 8); //Packet number
|
||||
buffer[2] = (uint8_t) (session_index & 0xFF);
|
||||
buffer[3] = 1; //Request session
|
||||
|
||||
this->write_message(buffer);
|
||||
}
|
||||
|
||||
void TSWebClient::send_status(bool flag_name) {
|
||||
this->state = S_DATA_EXCHANGE;
|
||||
|
||||
auto name = this->server->getDisplayName();
|
||||
pipes::buffer buffer{4 + 4 + 3 * 2 + 1 + 1 + (flag_name ? name.length() : 0)};
|
||||
|
||||
buffer[0] = 1; //Version
|
||||
buffer[1] = (uint8_t) (session_index >> 8); //Packet number
|
||||
buffer[2] = (uint8_t) (session_index & 0xFF);
|
||||
buffer[3] = 2; //Status update
|
||||
|
||||
*(uint32_t*) &buffer[4] = this->session_id;
|
||||
*(uint16_t*) &buffer[8] = this->server->properties()[property::VIRTUALSERVER_PORT].as<uint16_t>();
|
||||
*(uint16_t*) &buffer[10] = this->server->properties()[property::VIRTUALSERVER_MAXCLIENTS].as<uint16_t>();
|
||||
*(uint16_t*) &buffer[12] = this->server->properties()[property::VIRTUALSERVER_CLIENTS_ONLINE].as<uint16_t>();
|
||||
|
||||
bool flag_channel = this->server->could_default_create_channel();
|
||||
bool flag_password = this->server->properties()[property::VIRTUALSERVER_FLAG_PASSWORD].as<bool>();
|
||||
debugMessage(this->server->getServerId(), "[WebList] Sending properties: flag_channel: {}, flag_password: {}", flag_channel, flag_password);
|
||||
buffer[14] = (flag_password ? 0x01 : 0) | (flag_channel ? 0x02 : 0); //Create channels (0x01 = password)
|
||||
|
||||
if(flag_name) {
|
||||
buffer[15] = (uint8_t) name.length();
|
||||
if(name.length() > 0) {
|
||||
memcpy(&buffer[16], name.c_str(), name.length());
|
||||
}
|
||||
} else {
|
||||
buffer[15] = 0; //We dont want to send a server name
|
||||
}
|
||||
|
||||
this->write_message(buffer);
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <pipes/buffer.h>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <event.h>
|
||||
|
||||
namespace ts {
|
||||
namespace server {
|
||||
class VirtualServer;
|
||||
}
|
||||
|
||||
namespace weblist {
|
||||
class TSWebClient {
|
||||
public:
|
||||
enum State {
|
||||
S_UNINITIALIZED,
|
||||
S_INITIALIZING,
|
||||
S_DATA_EXCHANGE,
|
||||
S_FINALIZING,
|
||||
S_FINALIZED
|
||||
};
|
||||
|
||||
TSWebClient(const std::shared_ptr <server::VirtualServer> &server, struct event_base *event_base, uint16_t session_index, bool /* resend name */);
|
||||
virtual ~TSWebClient();
|
||||
|
||||
void report();
|
||||
void abort();
|
||||
void abort_sync();
|
||||
inline bool running() { return this->state != S_FINALIZED && this->state != S_UNINITIALIZED; }
|
||||
|
||||
std::function<void(const std::string&, bool)> callback_error;
|
||||
std::function<void()> callback_success;
|
||||
private:
|
||||
std::shared_ptr<server::VirtualServer> server;
|
||||
struct event_base* event_base = nullptr;
|
||||
std::thread close_thread;
|
||||
State state;
|
||||
|
||||
sockaddr_in remote_address{};
|
||||
std::mutex write_lock;
|
||||
std::deque<pipes::buffer> write_buffer{};
|
||||
int file_descriptor{0};
|
||||
|
||||
std::mutex event_mutex{};
|
||||
struct event* event_read{nullptr};
|
||||
struct event* event_write{nullptr};
|
||||
struct event* event_timeout{nullptr};
|
||||
|
||||
void unregister_events(bool /* blocking */);
|
||||
void reset_timeout(bool /* reschedule */);
|
||||
|
||||
static void _handle_message_read(int, short, void*);
|
||||
static void _handle_message_write(int, short, void*);
|
||||
static void _handle_timeout(int, short,void*);
|
||||
|
||||
void trigger_fail_later(const std::string& /* message */, bool /* retry */);
|
||||
void trigger_success_later();
|
||||
|
||||
void write_message(const pipes::buffer_view& /* buffer */);
|
||||
|
||||
private:
|
||||
void handle_message_read(const pipes::buffer_view& /* buffer */);
|
||||
|
||||
uint16_t session_index = 1;
|
||||
uint32_t session_id = 0;
|
||||
bool send_name = false;
|
||||
|
||||
void request_session();
|
||||
void send_status(bool /* name */);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <ThreadPool/ThreadHelper.h>
|
||||
#include "src/VirtualServer.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([&]{
|
||||
while(this->event_base) {
|
||||
::event_base_loop(this->event_base, EVLOOP_NO_EXIT_ON_EMPTY);
|
||||
|
||||
if(this->event_base) {
|
||||
logWarning(LOG_GENERAL, "WebList report event loop exited without terminating. Rescheduling....");
|
||||
std::this_thread::sleep_for(std::chrono::seconds{1});
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
WebListManager::~WebListManager() {
|
||||
auto event_base_ = std::exchange(this->event_base, nullptr);
|
||||
if(event_base_) {
|
||||
event_base_loopbreak(event_base_);
|
||||
}
|
||||
|
||||
threads::save_join(this->event_base_dispatch, true);
|
||||
if(event_base_) {
|
||||
event_base_free(event_base_);
|
||||
}
|
||||
}
|
||||
|
||||
void WebListManager::enable_report(const std::shared_ptr<ts::server::VirtualServer> &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::VirtualServer> &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::VirtualServer> &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 1 minute.");
|
||||
_entry->scheduled_request = now + seconds(60);
|
||||
} else if(_entry->fail_count == 2 && retry) {
|
||||
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 5 minutes.");
|
||||
_entry->scheduled_request = now + seconds(5 * 60);
|
||||
} else if(_entry->fail_count >= 3) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <deque>
|
||||
#include <condition_variable>
|
||||
|
||||
struct event_base;
|
||||
namespace ts {
|
||||
namespace server {
|
||||
class VirtualServer;
|
||||
}
|
||||
namespace weblist {
|
||||
class TSWebClient;
|
||||
class WebListManager {
|
||||
private:
|
||||
struct Entry {
|
||||
std::shared_ptr<server::VirtualServer> server;
|
||||
std::shared_ptr<TSWebClient> current_request;
|
||||
|
||||
std::chrono::system_clock::time_point last_success;
|
||||
std::chrono::system_clock::time_point scheduled_request;
|
||||
int fail_count = 0;
|
||||
|
||||
uint16_t session_count = 1;
|
||||
std::string last_name;
|
||||
};
|
||||
public:
|
||||
WebListManager();
|
||||
~WebListManager();
|
||||
|
||||
void enable_report(const std::shared_ptr<server::VirtualServer>& /* server */);
|
||||
bool reports_enabled(const std::shared_ptr<server::VirtualServer>& /* server */);
|
||||
void disable_report(const std::shared_ptr<server::VirtualServer>& /* server */);
|
||||
|
||||
void tick();
|
||||
|
||||
bool enabled = false;
|
||||
private:
|
||||
struct event_base* event_base{nullptr};
|
||||
std::thread event_base_dispatch{};
|
||||
|
||||
std::mutex entry_lock{};
|
||||
std::deque<std::shared_ptr<Entry>> entries{};
|
||||
};
|
||||
}
|
||||
}
|
2
shared
2
shared
@ -1 +1 @@
|
||||
Subproject commit 7ff7d01cd39795050cd8d6e4257e3e0d6dd4bc61
|
||||
Subproject commit 799bf8d26b5742e3e5df3c9ecbca233113d8f73d
|
Loading…
Reference in New Issue
Block a user