Some updates
This commit is contained in:
parent
74fa735004
commit
7ef77c3160
@ -1 +1 @@
|
||||
Subproject commit ed01d0360c5f980486e3bf83abdd3610d129aa7b
|
||||
Subproject commit 2da73d81d1ee4dcd9e4e7e06a4b7fdf2ee6074ea
|
@ -13,7 +13,7 @@ using namespace std::chrono;
|
||||
using namespace ts::server;
|
||||
|
||||
VirtualServerManager::VirtualServerManager(InstanceHandler* handle) : handle(handle) {
|
||||
this->puzzles = new protocol::PuzzleManager();
|
||||
this->puzzles = new udp::PuzzleManager{};
|
||||
this->handshakeTickers = new threads::Scheduler(1, "handshake ticker");
|
||||
this->execute_loop = new event::EventExecutor("executor #");
|
||||
//this->join_loop = new event::EventExecutor("joiner #");
|
||||
@ -67,7 +67,8 @@ bool VirtualServerManager::initialize(bool autostart) {
|
||||
this->state = State::STARTING;
|
||||
logMessage(LOG_INSTANCE, "Generating server puzzles...");
|
||||
auto start = system_clock::now();
|
||||
this->puzzles->precomputePuzzles(config::voice::DefaultPuzzlePrecomputeSize);
|
||||
if(!this->puzzles->precompute_puzzles(config::voice::DefaultPuzzlePrecomputeSize))
|
||||
logCritical(LOG_INSTANCE, "Failed to precompute RSA puzzles");
|
||||
logMessage(LOG_INSTANCE, "Puzzles generated! Time required: " + to_string(duration_cast<milliseconds>(system_clock::now() - start).count()) + "ms");
|
||||
|
||||
size_t serverCount = 0;
|
||||
|
@ -57,7 +57,7 @@ namespace ts {
|
||||
bool createServerSnapshot(Command &cmd, std::shared_ptr<VirtualServer> server, int version, std::string &error);
|
||||
std::shared_ptr<VirtualServer> createServerFromSnapshot(std::shared_ptr<VirtualServer> old, std::string, uint16_t, const ts::Command &, std::string &);
|
||||
|
||||
protocol::PuzzleManager* rsaPuzzles() { return this->puzzles; }
|
||||
udp::PuzzleManager* rsaPuzzles() { return this->puzzles; }
|
||||
|
||||
event::EventExecutor* get_join_loop() { return this->join_loop; }
|
||||
event::EventExecutor* get_executor_loop() { return this->execute_loop; }
|
||||
@ -80,7 +80,7 @@ namespace ts {
|
||||
InstanceHandler* handle;
|
||||
threads::Mutex instanceLock;
|
||||
std::deque<std::shared_ptr<VirtualServer>> instances;
|
||||
protocol::PuzzleManager* puzzles = nullptr;
|
||||
udp::PuzzleManager* puzzles{nullptr};
|
||||
|
||||
event::EventExecutor* execute_loop = nullptr;
|
||||
event::EventExecutor* join_loop = nullptr;
|
||||
|
@ -742,7 +742,7 @@ void SpeakingClient::processJoin() {
|
||||
|
||||
unique_lock server_channel_lock(this->server->channel_tree_lock);
|
||||
this->server->client_move(this->ref(), channel, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, server_channel_lock);
|
||||
this->subscribeChannel({this->currentChannel}, false, true);
|
||||
if(this->getType() != ClientType::CLIENT_TEAMSPEAK) this->subscribeChannel({this->currentChannel}, false, true); /* su "improve" the TS3 clients join speed we send the channel clients a bit later, when the TS3 client gets his own client variables */
|
||||
}
|
||||
TIMING_STEP(timings, "join move ");
|
||||
|
||||
|
@ -39,17 +39,21 @@ using namespace ts::token;
|
||||
command_result ConnectedClient::handleCommandClientGetVariables(Command &cmd) {
|
||||
CMD_REQ_SERVER;
|
||||
ConnectedLockedClient client{this->server->find_client_by_id(cmd["clid"].as<ClientId>())};
|
||||
shared_lock tree_lock(this->channel_lock);
|
||||
{
|
||||
shared_lock tree_lock(this->channel_lock);
|
||||
|
||||
if (!client || (client.client != this && !this->isClientVisible(client.client, false)))
|
||||
return command_result{error::client_invalid_id, ""};
|
||||
if (!client || (client.client != this && !this->isClientVisible(client.client, false)))
|
||||
return command_result{error::client_invalid_id, ""};
|
||||
|
||||
deque<const property::PropertyDescription*> props;
|
||||
for (auto &prop : client->properties()->list_properties(property::FLAG_CLIENT_VARIABLE, this->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0)) {
|
||||
props.push_back(&prop.type());
|
||||
deque<const property::PropertyDescription*> props;
|
||||
for (auto &prop : client->properties()->list_properties(property::FLAG_CLIENT_VARIABLE, this->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0)) {
|
||||
props.push_back(&prop.type());
|
||||
}
|
||||
|
||||
this->notifyClientUpdated(client.client, props, false);
|
||||
}
|
||||
|
||||
this->notifyClientUpdated(client.client, props, false);
|
||||
if(client.client == this && this->getType() == ClientType::CLIENT_TEAMSPEAK)
|
||||
this->subscribeChannel({this->currentChannel}, true, true); /* lets show the clients in the current channel because we've not done that while joining (speed improvement ;))*/
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,34 @@ void PacketStatistics::tick() {
|
||||
}
|
||||
}
|
||||
|
||||
void PacketStatistics::reset() {
|
||||
std::lock_guard lock{this->data_mutex};
|
||||
this->calculator_command.reset();
|
||||
this->calculator_command_low.reset();
|
||||
|
||||
this->calculator_ack.reset();
|
||||
this->calculator_ack_low.reset();
|
||||
|
||||
this->calculator_voice.reset();
|
||||
this->calculator_voice_whisper.reset();
|
||||
|
||||
this->calculator_ping.reset();
|
||||
}
|
||||
|
||||
void PacketStatistics::reset_offsets() {
|
||||
std::lock_guard lock{this->data_mutex};
|
||||
this->calculator_command.reset_offsets();
|
||||
this->calculator_command_low.reset_offsets();
|
||||
|
||||
this->calculator_ack.reset_offsets();
|
||||
this->calculator_ack_low.reset_offsets();
|
||||
|
||||
this->calculator_voice.reset_offsets();
|
||||
this->calculator_voice_whisper.reset_offsets();
|
||||
|
||||
this->calculator_ping.reset_offsets();
|
||||
}
|
||||
|
||||
float PacketStatistics::current_packet_loss() const {
|
||||
auto report = this->loss_report();
|
||||
return report.total_loss();
|
||||
|
@ -48,6 +48,8 @@ namespace ts::server::client {
|
||||
|
||||
void received_packet(protocol::PacketType /* type */, uint32_t /* packet id */);
|
||||
void tick();
|
||||
void reset();
|
||||
void reset_offsets();
|
||||
private:
|
||||
std::chrono::system_clock::time_point last_short{};
|
||||
|
||||
|
@ -1,50 +1,51 @@
|
||||
#include "PrecomputedPuzzles.h"
|
||||
#include "../../Configuration.h"
|
||||
#include "../ConnectedClient.h"
|
||||
#include "./PrecomputedPuzzles.h"
|
||||
#include "src/Configuration.h"
|
||||
#include <tomcrypt.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace ts;
|
||||
using namespace ts::protocol;
|
||||
using namespace ts::server::udp;
|
||||
|
||||
PuzzleManager::PuzzleManager() {}
|
||||
PuzzleManager::~PuzzleManager() {}
|
||||
PuzzleManager::PuzzleManager() = default;
|
||||
PuzzleManager::~PuzzleManager() = default;
|
||||
|
||||
size_t PuzzleManager::precomputedPuzzleCount() { return this->cached.size(); }
|
||||
|
||||
bool PuzzleManager::precomputePuzzles(size_t limit) {
|
||||
while(precomputedPuzzleCount() < limit) generatePuzzle();
|
||||
return true;
|
||||
size_t PuzzleManager::precomputed_puzzle_count() {
|
||||
std::lock_guard lock{this->cache_lock};
|
||||
return this->cached_puzzles.size();
|
||||
}
|
||||
|
||||
std::shared_ptr<Puzzle> PuzzleManager::nextPuzzle() {
|
||||
this->indexLock.lock();
|
||||
size_t index = this->cacheIndex++ % this->cached.size();
|
||||
this->indexLock.unlock();
|
||||
return this->cached[index];
|
||||
bool PuzzleManager::precompute_puzzles(size_t amount) {
|
||||
std::random_device rd{};
|
||||
std::mt19937 mt{rd()};
|
||||
|
||||
amount = 5;
|
||||
while(this->precomputed_puzzle_count() < amount)
|
||||
this->generate_puzzle(mt);
|
||||
return this->precomputed_puzzle_count() > 0;
|
||||
}
|
||||
|
||||
inline void rndNum(mp_int *result, int byteLength){
|
||||
uint8_t buffer[byteLength];
|
||||
std::shared_ptr<Puzzle> PuzzleManager::next_puzzle() {
|
||||
std::lock_guard lock{this->cache_lock};
|
||||
return this->cached_puzzles[this->cache_index++ % this->cached_puzzles.size()];
|
||||
}
|
||||
|
||||
for(int index = 0; index < byteLength; index++) {
|
||||
int rnd = rand();
|
||||
uint8_t urnd = static_cast<uint8_t>(rnd & 0xFF);
|
||||
buffer[index] = urnd; //TODO more secure!
|
||||
inline void random_number(std::mt19937& generator, mp_int *result, int length){
|
||||
std::uniform_int_distribution<uint8_t> dist{};
|
||||
|
||||
}
|
||||
uint8_t buffer[length];
|
||||
for(auto& byte : buffer)
|
||||
byte = dist(generator);
|
||||
|
||||
mp_zero(result);
|
||||
mp_read_unsigned_bin(result, buffer, byteLength);
|
||||
mp_read_unsigned_bin(result, buffer, length);
|
||||
}
|
||||
|
||||
inline bool solvePuzzle(Puzzle *puzzle){
|
||||
inline bool solve_puzzle(Puzzle *puzzle) {
|
||||
mp_int exp{};
|
||||
mp_init(&exp);
|
||||
mp_2expt(&exp, puzzle->level);
|
||||
|
||||
|
||||
if (mp_exptmod(&puzzle->x, &exp, &puzzle->n, &puzzle->result) != CRYPT_OK) { //Sometimes it fails (unknow why :D)
|
||||
if (mp_exptmod(&puzzle->x, &exp, &puzzle->n, &puzzle->result) != CRYPT_OK) { //Sometimes it fails (unknown why :D)
|
||||
mp_clear(&exp);
|
||||
return false;
|
||||
}
|
||||
@ -66,17 +67,17 @@ inline bool write_bin_data(mp_int& data, uint8_t* result, size_t length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PuzzleManager::generatePuzzle() {
|
||||
void PuzzleManager::generate_puzzle(std::mt19937& random_generator) {
|
||||
auto puzzle = new Puzzle{};
|
||||
|
||||
puzzle->level = ts::config::voice::RsaPuzzleLevel;
|
||||
mp_init_multi(&puzzle->x, &puzzle->n, &puzzle->result, nullptr);
|
||||
|
||||
generate_new:
|
||||
rndNum(&puzzle->x, 64);
|
||||
rndNum(&puzzle->n, 64);
|
||||
puzzle->level = ts::config::voice::RsaPuzzleLevel;
|
||||
random_number(random_generator, &puzzle->x, 64);
|
||||
random_number(random_generator, &puzzle->n, 64);
|
||||
|
||||
if(!solvePuzzle(puzzle))
|
||||
if(!solve_puzzle(puzzle))
|
||||
goto generate_new;
|
||||
|
||||
auto valid_x = mp_unsigned_bin_size(&puzzle->x) <= 64;
|
||||
@ -94,7 +95,7 @@ void PuzzleManager::generatePuzzle() {
|
||||
if(!write_bin_data(puzzle->result, puzzle->data_result, 64))
|
||||
goto generate_new;
|
||||
|
||||
this->cached.push_back(shared_ptr<Puzzle>(puzzle, [](Puzzle* elm){
|
||||
this->cached_puzzles.push_back(shared_ptr<Puzzle>(puzzle, [](Puzzle* elm){
|
||||
mp_clear_multi(&elm->n, &elm->x, &elm->result, nullptr);
|
||||
delete elm;
|
||||
}));
|
||||
|
@ -1,44 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <ThreadPool/Mutex.h>
|
||||
#include <tommath.h>
|
||||
#include <memory>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <misc/spin_lock.h>
|
||||
#include <random>
|
||||
|
||||
namespace ts {
|
||||
namespace server {
|
||||
class ConnectedClient;
|
||||
}
|
||||
namespace ts::server::udp {
|
||||
struct Puzzle {
|
||||
mp_int x;
|
||||
mp_int n;
|
||||
int level;
|
||||
|
||||
namespace protocol {
|
||||
struct Puzzle {
|
||||
mp_int x;
|
||||
mp_int n;
|
||||
int level;
|
||||
mp_int result;
|
||||
|
||||
mp_int result;
|
||||
uint8_t data_x[64];
|
||||
uint8_t data_n[64];
|
||||
uint8_t data_result[64];
|
||||
};
|
||||
|
||||
uint8_t data_x[64];
|
||||
uint8_t data_n[64];
|
||||
uint8_t data_result[64];
|
||||
};
|
||||
class PuzzleManager {
|
||||
public:
|
||||
PuzzleManager();
|
||||
~PuzzleManager();
|
||||
class PuzzleManager {
|
||||
public:
|
||||
PuzzleManager();
|
||||
~PuzzleManager();
|
||||
|
||||
bool precomputePuzzles(size_t limit);
|
||||
[[nodiscard]] bool precompute_puzzles(size_t amount);
|
||||
|
||||
size_t precomputedPuzzleCount();
|
||||
[[nodiscard]] size_t precomputed_puzzle_count();
|
||||
|
||||
std::shared_ptr<Puzzle> nextPuzzle();
|
||||
private:
|
||||
void generatePuzzle();
|
||||
[[nodiscard]] std::shared_ptr<Puzzle> next_puzzle();
|
||||
private:
|
||||
void generate_puzzle(std::mt19937&);
|
||||
|
||||
threads::Mutex indexLock;
|
||||
size_t cacheIndex = 0;
|
||||
|
||||
std::deque<std::shared_ptr<Puzzle>> cached;
|
||||
};
|
||||
}
|
||||
size_t cache_index{0};
|
||||
spin_lock cache_lock{};
|
||||
std::vector<std::shared_ptr<Puzzle>> cached_puzzles{};
|
||||
};
|
||||
}
|
@ -70,6 +70,7 @@ ts::command_result VoiceClient::handleCommandClientInitIv(Command& command) {
|
||||
|
||||
this->connection->reset();
|
||||
this->connection->register_initiv_packet();
|
||||
this->connection->packet_statistics().reset_offsets();
|
||||
this->crypto.protocol_encrypted = false;
|
||||
|
||||
bool use_teaspeak = command.hasParm("teaspeak");
|
||||
|
@ -1,10 +1,8 @@
|
||||
#include "POWHandler.h"
|
||||
#include "src/InstanceHandler.h"
|
||||
#include "src/VirtualServerManager.h"
|
||||
#include "src/client/voice/VoiceClient.h"
|
||||
#include <misc/endianness.h>
|
||||
#include <log/LogUtils.h>
|
||||
#include <src/client/voice/VoiceClient.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
@ -21,7 +19,7 @@ void POWHandler::execute_tick() {
|
||||
|
||||
lock_guard lock(this->pending_clients_lock);
|
||||
this->pending_clients.erase(remove_if(this->pending_clients.begin(), this->pending_clients.end(), [&, now](const shared_ptr<Client>& client) {
|
||||
if(now - client->last_packet > seconds(5)) {
|
||||
if(now - client->last_packet > std::chrono::seconds{5}) {
|
||||
#ifdef POW_ERROR
|
||||
if(client->state != LowHandshakeState::COMPLETED) { /* handshake succeeded */
|
||||
debugMessage(this->get_server_id(), "[POW] Dropping connection from {} (Timeout)", net::to_string(client->address));
|
||||
@ -155,12 +153,6 @@ inline void generate_random(uint8_t *destination, size_t length) {
|
||||
*(destination++) = (uint8_t) rand();
|
||||
}
|
||||
|
||||
inline void write_reversed(uint8_t* destination, uint8_t* source, size_t length) {
|
||||
destination += length;
|
||||
while(length-- > 0)
|
||||
*(--destination) = *(source++);
|
||||
}
|
||||
|
||||
void POWHandler::handle_cookie_get(const std::shared_ptr<ts::server::POWHandler::Client> &client, const pipes::buffer_view &buffer) {
|
||||
if(buffer.length() != 21) {
|
||||
#ifdef POW_ERROR
|
||||
@ -172,7 +164,7 @@ void POWHandler::handle_cookie_get(const std::shared_ptr<ts::server::POWHandler:
|
||||
/* initialize data */
|
||||
if(client->server_control_data[0] == 0) {
|
||||
generate_random(client->server_control_data, 16);
|
||||
client->server_control_data[0] |= 1;
|
||||
client->server_control_data[0] |= 1U;
|
||||
}
|
||||
|
||||
/* parse values */
|
||||
@ -183,7 +175,7 @@ void POWHandler::handle_cookie_get(const std::shared_ptr<ts::server::POWHandler:
|
||||
uint8_t response_buffer[21];
|
||||
response_buffer[0] = LowHandshakeState::COOKIE_SET;
|
||||
memcpy(&response_buffer[1], client->server_control_data, 16);
|
||||
write_reversed(&response_buffer[17], client->client_control_data, 4);
|
||||
*(uint32_t*) &response_buffer[17] = htonl(*(uint32_t*) &client->client_control_data);
|
||||
|
||||
this->send_data(client, pipes::buffer_view{response_buffer, 21});
|
||||
}
|
||||
@ -211,7 +203,7 @@ void POWHandler::handle_puzzle_get(const std::shared_ptr<ts::server::POWHandler:
|
||||
}
|
||||
|
||||
if(!client->rsa_challenge)
|
||||
client->rsa_challenge = serverInstance->getVoiceServerManager()->rsaPuzzles()->nextPuzzle();
|
||||
client->rsa_challenge = serverInstance->getVoiceServerManager()->rsaPuzzles()->next_puzzle();
|
||||
|
||||
/* send response */
|
||||
{
|
||||
@ -262,6 +254,7 @@ void POWHandler::handle_puzzle_solve(const std::shared_ptr<ts::server::POWHandle
|
||||
#ifdef POW_ERROR
|
||||
debugMessage(this->get_server_id(), "[POW][{}][Puzzle] Received an invalid puzzle solution! Resetting client", net::to_string(client->address));
|
||||
#endif
|
||||
client->rsa_challenge.reset(); /* get another RSA challenge */
|
||||
this->reset_client(client);
|
||||
return;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "VoiceServer.h"
|
||||
#include "src/VirtualServer.h"
|
||||
|
||||
|
||||
namespace ts::server {
|
||||
class POWHandler {
|
||||
public:
|
||||
@ -32,13 +33,13 @@ namespace ts::server {
|
||||
std::chrono::system_clock::time_point last_packet;
|
||||
LowHandshakeState state = LowHandshakeState::COOKIE_GET;
|
||||
|
||||
uint8_t client_control_data[4] = {0,0,0,0};
|
||||
uint8_t server_control_data[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
uint8_t client_control_data[4]{0};
|
||||
uint8_t server_control_data[16]{0};
|
||||
uint8_t server_data[100];
|
||||
|
||||
uint32_t client_version;
|
||||
|
||||
std::shared_ptr<protocol::Puzzle> rsa_challenge;
|
||||
std::shared_ptr<udp::Puzzle> rsa_challenge;
|
||||
};
|
||||
|
||||
explicit POWHandler(VoiceServer* /* server */);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <condition_variable>
|
||||
#include <pipes/buffer.h>
|
||||
#include <misc/spin_lock.h>
|
||||
#include <ThreadPool/Mutex.h>
|
||||
|
||||
namespace ts {
|
||||
namespace server {
|
||||
|
@ -170,11 +170,11 @@ void VoiceServer::execute_resend(const std::chrono::system_clock::time_point &no
|
||||
}
|
||||
for(auto& entry : buffers)
|
||||
connection->packet_statistics().send_command((protocol::PacketType) entry->packet_type, entry->packet_id | entry->generation_id << 16U);
|
||||
if(buffers.size() > 0)
|
||||
logTrace(client->getServerId(), "{} Resending {} packets.", CLIENT_STR_LOG_PREFIX_(client), buffers.size());
|
||||
buffers.clear();
|
||||
//if(buffers.size() > 0)
|
||||
// logTrace(client->getServerId(), "{} Resending {} packets.", CLIENT_STR_LOG_PREFIX_(client), buffers.size());
|
||||
connection->triggerWrite();
|
||||
}
|
||||
buffers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
2
shared
2
shared
@ -1 +1 @@
|
||||
Subproject commit e0eb4c5a16b900f6ed906c88a264d07479b13c5e
|
||||
Subproject commit ee7f26b7ed883027f0a81ece1c2aacd41053ce1e
|
Loading…
Reference in New Issue
Block a user