Some minor changes

This commit is contained in:
WolverinDEV 2020-12-02 21:00:51 +01:00
parent 58dce86e0f
commit 8e7c207720
10 changed files with 217 additions and 135 deletions

View File

@ -3,7 +3,7 @@ import {
AbstractServerConnection,
CommandOptionDefaults,
CommandOptions,
ConnectionStateListener, ConnectionStatistics,
ConnectionStatistics,
ServerCommand
} from "tc-shared/connection/ConnectionBase";
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
@ -353,9 +353,11 @@ export class ServerConnection extends AbstractServerConnection {
}
getControlStatistics(): ConnectionStatistics {
const stats = this.nativeHandle?.statistics();
return {
bytesReceived: 0,
bytesSend: 0
bytesReceived: stats?.control_bytes_received ? stats?.control_bytes_received : 0,
bytesSend: stats?.control_bytes_send ? stats?.control_bytes_send : 0
};
}

View File

@ -4,7 +4,7 @@ import {
WhisperSessionInitializer
} from "tc-shared/connection/VoiceConnection";
import {RecorderProfile} from "tc-shared/voice/RecorderProfile";
import {NativeVoiceClient, NativeVoiceConnection, PlayerState} from "tc-native/connection";
import {NativeServerConnection, NativeVoiceClient, NativeVoiceConnection, PlayerState} from "tc-native/connection";
import {ServerConnection} from "./ServerConnection";
import {VoiceClient} from "tc-shared/voice/VoiceClient";
import {WhisperSession, WhisperTarget} from "tc-shared/voice/VoiceWhisper";
@ -231,9 +231,12 @@ export class NativeVoiceConnectionWrapper extends AbstractVoiceConnection {
}
getConnectionStats(): Promise<ConnectionStatistics> {
/* FIXME: This is iffy! */
const stats = (this.connection as any as NativeServerConnection)["nativeHandle"]?.statistics();
return Promise.resolve({
bytesSend: 0,
bytesReceived: 0
bytesSend: stats?.voice_bytes_send ? stats?.voice_bytes_send : 0,
bytesReceived: stats?.voice_bytes_received ? stats?.voice_bytes_received : 0
});
}

View File

@ -22,7 +22,7 @@ message("Module path: ${CMAKE_MODULE_PATH}")
function(setup_nodejs)
set(NodeJS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
set(NODEJS_URL "https://atom.io/download/atom-shell")
set(NODEJS_VERSION "v11.0.3")
set(NODEJS_VERSION "v8.0.0")
#set(NODEJS_URL "https://nodejs.org/download/release/")
#set(NODEJS_VERSION "v12.13.0")

View File

@ -78,6 +78,8 @@ declare module "tc-native/connection" {
/* ping in microseconds */
current_ping() : number;
statistics() : { voice_bytes_received: number, voice_bytes_send: number, control_bytes_received: number, control_bytes_send } | undefined
}
export function spawn_server_connection() : NativeServerConnection;

View File

@ -67,6 +67,11 @@ void ProtocolHandler::reset() {
this->crypt_handler.reset();
this->ping.ping_received_timestamp = system_clock::time_point{};
this->statistics_.control_bytes_received = 0;
this->statistics_.control_bytes_send = 0;
this->statistics_.voice_bytes_send = 0;
this->statistics_.voice_bytes_received = 0;
}
void ProtocolHandler::connect() {
@ -125,8 +130,9 @@ void ProtocolHandler::execute_tick() {
}
void ProtocolHandler::execute_resend() {
if(this->connection_state >= connection_state::DISCONNECTED)
if(this->connection_state >= connection_state::DISCONNECTED) {
return;
}
std::deque<std::shared_ptr<ts::connection::AcknowledgeManager::Entry>> buffers;
auto now = system_clock::now();
@ -145,8 +151,12 @@ void ProtocolHandler::execute_resend() {
auto socket = this->handle->get_socket();
if(socket) {
for(const auto& buffer : buffers)
for(const auto& buffer : buffers) {
socket->send_message(buffer->buffer);
/* only control packets are getting resend */
this->statistics_.control_bytes_send += buffer->buffer.length();
}
}
this->handle->schedule_resend(next);
@ -169,11 +179,17 @@ void ProtocolHandler::progress_packet(const pipes::buffer_view &buffer) {
auto ordered = packet_type.type() == protocol::COMMAND || packet_type.type() == protocol::COMMAND_LOW;
//log_trace(category::connection, tr("Received packet {} with id {}"), packet->type().name(), packet->packetId());
/*
if(ordered)
if(rand() & 1)
return;
*/
switch(packet_type.type()) {
case ts::protocol::PacketType::VOICE:
case ts::protocol::PacketType::VOICE_WHISPER:
this->statistics_.voice_bytes_received += buffer.length();
break;
case ts::protocol::PacketType::COMMAND:
case ts::protocol::PacketType::COMMAND_LOW:
this->statistics_.control_bytes_received += buffer.length();
break;
}
/* special handling */
if(packet_type.type() == protocol::INIT1) {
@ -565,6 +581,7 @@ void ProtocolHandler::send_command(const ts::Command &cmd, const std::function<v
//log_trace(category::connection, tr("Time needed for command: {}ms. Success: {}"), chrono::duration_cast<chrono::milliseconds>(end - begin).count(), f);
});
}
packet->enable_flag(PacketFlag::NewProtocol);
this->send_packet(packet);
}
@ -594,8 +611,24 @@ void ProtocolHandler::send_packet(const std::shared_ptr<ts::protocol::ClientPack
return;
}
for(const auto& buffer : result)
size_t total_size{0};
for(const auto& buffer : result) {
socket->send_message(buffer);
total_size += buffer.length();
}
switch(packet->type().type()) {
case ts::protocol::PacketType::VOICE:
case ts::protocol::PacketType::VOICE_WHISPER:
this->statistics_.voice_bytes_send += total_size;
break;
case ts::protocol::PacketType::COMMAND:
case ts::protocol::PacketType::COMMAND_LOW:
this->statistics_.control_bytes_send += total_size;
break;
}
}
void ProtocolHandler::send_acknowledge(uint16_t packet_id, bool low) {
@ -632,4 +665,8 @@ void ProtocolHandler::disconnect(const std::string &reason) {
if(success && this->connection_state == connection_state::DISCONNECTING && this->disconnect_id == did)
this->handle->close_connection();
});
}
const ConnectionStatistics& ProtocolHandler::statistics() {
return this->statistics_;
}

View File

@ -16,139 +16,147 @@
#include <protocol/generation.h>
#include "ServerConnection.h"
namespace ts {
namespace connection {
class CryptionHandler;
class CompressionHandler;
}
namespace ts::connection {
class CryptionHandler;
class CompressionHandler;
}
namespace tc {
namespace connection {
class ServerConnection;
namespace tc::connection {
class ServerConnection;
namespace connection_state {
enum value {
INITIALIZING,
INIT_LOW,
INIT_HIGH,
CONNECTING,
CONNECTED,
DISCONNECTING,
DISCONNECTED
};
};
namespace pow_state {
enum value : uint8_t {
COOKIE_GET,
COOKIE_SET,
PUZZLE_GET,
PUZZLE_SET,
PUZZLE_SOLVE,
PUZZLE_RESET,
COMPLETED,
COMMAND_RESET = 127,
UNSET = 0xFB
};
};
namespace connection_state {
enum value {
INITIALIZING,
INIT_LOW,
INIT_HIGH,
CONNECTING,
CONNECTED,
DISCONNECTING,
DISCONNECTED
};
};
namespace pow_state {
enum value : uint8_t {
COOKIE_GET,
COOKIE_SET,
PUZZLE_GET,
PUZZLE_SET,
PUZZLE_SOLVE,
PUZZLE_RESET,
COMPLETED,
COMMAND_RESET = 127,
UNSET = 0xFB
};
};
class ProtocolHandler {
typedef ts::protocol::PacketRingBuffer<ts::protocol::ServerPacket, 88> packet_buffer_t;
typedef std::array<packet_buffer_t, 8> packet_buffers_t;
friend class ServerConnection;
public:
ProtocolHandler(ServerConnection*);
~ProtocolHandler();
struct ConnectionStatistics {
size_t control_bytes_send{0};
size_t control_bytes_received{0};
void reset();
void connect();
void execute_tick();
void execute_resend();
size_t voice_bytes_send{0};
size_t voice_bytes_received{0};
};
void progress_packet(const pipes::buffer_view& /* buffer */);
bool handle_packets(); /* if true we have more left */
void send_packet(const std::shared_ptr<ts::protocol::ClientPacket>& /* packet */);
void send_command(const ts::Command& /* command */, const std::function<void(bool)> & /* acknowledge callback */ = NULL);
class ProtocolHandler {
typedef ts::protocol::PacketRingBuffer<ts::protocol::ServerPacket, 88> packet_buffer_t;
typedef std::array<packet_buffer_t, 8> packet_buffers_t;
friend class ServerConnection;
public:
explicit ProtocolHandler(ServerConnection*);
~ProtocolHandler();
void disconnect(const std::string& /* message */);
void reset();
void connect();
void execute_tick();
void execute_resend();
void send_acknowledge(uint16_t /* packet id */, bool /* low */);
const ConnectionStatistics& statistics();
ecc_key& get_identity_key() { return this->crypto.identity; }
void progress_packet(const pipes::buffer_view& /* buffer */);
bool handle_packets(); /* if true we have more left */
void send_packet(const std::shared_ptr<ts::protocol::ClientPacket>& /* packet */);
void send_command(const ts::Command& /* command */, const std::function<void(bool)> & /* acknowledge callback */ = NULL);
inline std::chrono::microseconds current_ping() { return this->ping.value; }
void disconnect(const std::string& /* message */);
void send_acknowledge(uint16_t /* packet id */, bool /* low */);
connection_state::value connection_state = connection_state::INITIALIZING;
server_type::value server_type = server_type::TEASPEAK;
private:
void do_close_connection(); /* only call from ServerConnection. Close all connections via ServerConnection! */
ecc_key& get_identity_key() { return this->crypto.identity; }
void handlePacketCommand(const std::shared_ptr<ts::protocol::ServerPacket>&);
void handlePacketAck(const std::shared_ptr<ts::protocol::ServerPacket>&);
void handlePacketVoice(const std::shared_ptr<ts::protocol::ServerPacket>&);
void handlePacketPing(const std::shared_ptr<ts::protocol::ServerPacket>&);
void handlePacketInit(const std::shared_ptr<ts::protocol::ServerPacket>&);
inline std::chrono::microseconds current_ping() { return this->ping.value; }
bool create_datagram_packets(std::vector<pipes::buffer> &result, const std::shared_ptr<ts::protocol::ClientPacket> &packet);
connection_state::value connection_state = connection_state::INITIALIZING;
server_type::value server_type = server_type::TEASPEAK;
private:
void do_close_connection(); /* only call from ServerConnection. Close all connections via ServerConnection! */
ServerConnection* handle;
void handlePacketCommand(const std::shared_ptr<ts::protocol::ServerPacket>&);
void handlePacketAck(const std::shared_ptr<ts::protocol::ServerPacket>&);
void handlePacketVoice(const std::shared_ptr<ts::protocol::ServerPacket>&);
void handlePacketPing(const std::shared_ptr<ts::protocol::ServerPacket>&);
void handlePacketInit(const std::shared_ptr<ts::protocol::ServerPacket>&);
std::chrono::system_clock::time_point connect_timestamp;
std::chrono::system_clock::time_point disconnect_timestamp;
uint8_t disconnect_id = 0;
bool create_datagram_packets(std::vector<pipes::buffer> &result, const std::shared_ptr<ts::protocol::ClientPacket> &packet);
struct {
size_t retry_count{0};
pow_state::value state;
ServerConnection* handle;
uint64_t client_ts3_build_timestamp = 173265950 /* TS3 */; /* needs to be lower than 173265950 for old stuff, else new protocol */
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 server_data[100];
std::chrono::system_clock::time_point connect_timestamp;
std::chrono::system_clock::time_point disconnect_timestamp;
uint8_t disconnect_id = 0;
std::chrono::system_clock::time_point last_response;
std::chrono::system_clock::time_point last_resend;
pipes::buffer last_buffer;
} pow;
void pow_send_cookie_get();
struct {
size_t retry_count{0};
pow_state::value state;
struct {
uint8_t alpha[10];
uint8_t beta[54];
uint8_t beta_length; /* 10 or 54 */
uint64_t client_ts3_build_timestamp = 173265950 /* TS3 */; /* needs to be lower than 173265950 for old stuff, else new protocol */
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 server_data[100];
ecc_key identity{};
std::chrono::system_clock::time_point last_response;
std::chrono::system_clock::time_point last_resend;
pipes::buffer last_buffer;
} pow;
void pow_send_cookie_get();
std::string initiv_command;
} crypto;
std::string generate_client_initiv();
struct {
uint8_t alpha[10];
uint8_t beta[54];
uint8_t beta_length; /* 10 or 54 */
uint16_t client_id = 0;
ts::protocol::PacketIdManager _packet_id_manager;
packet_buffers_t _packet_buffers;
std::array<bool, 9> _packet_buffer_overflow{false};
ecc_key identity{};
std::array<ts::protocol::generation_estimator, 9> incoming_generation_estimators{}; /* implementation is thread save */
uint8_t _packet_buffers_index = 0;
std::string initiv_command;
} crypto;
std::string generate_client_initiv();
bool crypt_setupped{false};
ts::connection::CryptHandler crypt_handler;
ts::connection::CompressionHandler compression_handler;
ts::connection::AcknowledgeManager acknowledge_handler;
uint16_t client_id = 0;
ts::protocol::PacketIdManager _packet_id_manager;
packet_buffers_t _packet_buffers;
std::array<bool, 9> _packet_buffer_overflow{false};
void handleCommandInitIVExpend(ts::Command&);
void handleCommandInitIVExpend2(ts::Command&);
void handleCommandInitServer(ts::Command&);
std::array<ts::protocol::generation_estimator, 9> incoming_generation_estimators{}; /* implementation is thread save */
uint8_t _packet_buffers_index = 0;
struct {
std::chrono::system_clock::time_point ping_send_timestamp;
std::chrono::system_clock::time_point ping_received_timestamp;
std::chrono::microseconds value;
uint16_t ping_id;
bool crypt_setupped{false};
ts::connection::CryptHandler crypt_handler;
ts::connection::CompressionHandler compression_handler;
ts::connection::AcknowledgeManager acknowledge_handler;
std::chrono::microseconds interval = std::chrono::microseconds(2500);
} ping;
void ping_send_request();
};
}
ConnectionStatistics statistics_{};
struct {
std::chrono::system_clock::time_point ping_send_timestamp{};
std::chrono::system_clock::time_point ping_received_timestamp{};
std::chrono::microseconds value{0};
uint16_t ping_id{0};
std::chrono::microseconds interval{2500};
} ping;
void handleCommandInitIVExpend(ts::Command&);
void handleCommandInitIVExpend2(ts::Command&);
void handleCommandInitServer(ts::Command&);
void ping_send_request();
};
}

View File

@ -16,14 +16,16 @@ using namespace ts::protocol;
using namespace ts;
inline void generate_random(uint8_t *destination, size_t length) {
while(length-- > 0)
*(destination++) = (uint8_t) rand();
while(length-- > 0) {
*(destination++) = (uint8_t) rand();
}
}
inline void write_reversed(uint8_t* destination, uint8_t* source, size_t length) {
destination += length;
while(length-- > 0)
*(--destination) = *(source++);
while(length-- > 0) {
*(--destination) = *(source++);
}
}
inline bool solve_puzzle(mp_int& x, mp_int& n, mp_int& result, uint32_t level) {
@ -63,8 +65,10 @@ void ProtocolHandler::handlePacketInit(const std::shared_ptr<ts::protocol::Serve
}
log_trace(category::connection, tr("[POW] State {} | {}"), packet_state, data.length());
if(packet_state != this->pow.state)
return; //TODO handle error?
if(packet_state != this->pow.state) {
return; //TODO handle error?
}
this->acknowledge_handler.reset(); /* we don't need an ack anymore for our init packet */
if(packet_state == pow_state::COOKIE_SET) {
@ -146,6 +150,7 @@ void ProtocolHandler::handlePacketInit(const std::shared_ptr<ts::protocol::Serve
this->pow.last_resend = system_clock::now();
this->send_packet(make_shared<ClientPacket>(PacketTypeInfo::Init1, PacketFlag::Unencrypted, this->pow.last_buffer));
}
mp_clear_multi(&point_x, &point_n, &result, nullptr);
this->connection_state = connection_state::INIT_HIGH;
}

View File

@ -65,6 +65,7 @@ NAN_MODULE_INIT(ServerConnection::Init) {
Nan::SetPrototypeMethod(klass, "send_voice_data", ServerConnection::_send_voice_data);
Nan::SetPrototypeMethod(klass, "send_voice_data_raw", ServerConnection::_send_voice_data_raw);
Nan::SetPrototypeMethod(klass, "current_ping", ServerConnection::_current_ping);
Nan::SetPrototypeMethod(klass, "statistics", ServerConnection::statistics);
constructor().Reset(Nan::GetFunction(klass).ToLocalChecked());
}
@ -620,7 +621,7 @@ void ServerConnection::send_voice_data(const void *buffer, size_t buffer_length,
}
void ServerConnection::close_connection() {
lock_guard lock(this->disconnect_lock);
lock_guard lock{this->disconnect_lock};
if(this->socket && this_thread::get_id() == this->socket->io_thread().get_id()) {
logger::debug(category::connection, tr("close_connection() called in IO thread. Closing connection within event loop!"));
if(!this->event_loop_execute_connection_close) {
@ -643,11 +644,13 @@ void ServerConnection::close_connection() {
}
void ServerConnection::execute_tick() {
if(this->protocol_handler)
this->protocol_handler->execute_tick();
if(this->protocol_handler) {
this->protocol_handler->execute_tick();
}
if(auto vc{this->voice_connection}; vc)
vc->execute_tick();
if(auto vc{this->voice_connection}; vc) {
vc->execute_tick();
}
}
void ServerConnection::_execute_callback_commands() {
@ -759,9 +762,30 @@ void ServerConnection::_execute_callback_disconnect(const std::string &reason) {
NAN_METHOD(ServerConnection::_current_ping) {
auto connection = ObjectWrap::Unwrap<ServerConnection>(info.Holder());
lock_guard lock{connection->disconnect_lock};
auto& phandler = connection->protocol_handler;
if(phandler)
info.GetReturnValue().Set((uint32_t) chrono::floor<microseconds>(phandler->current_ping()).count());
else
info.GetReturnValue().Set(-1);
}
NAN_METHOD(ServerConnection::statistics) {
auto connection = ObjectWrap::Unwrap<ServerConnection>(info.Holder());
lock_guard lock{connection->disconnect_lock};
auto& phandler = connection->protocol_handler;
if(phandler) {
auto statistics = phandler->statistics();
auto result = Nan::New<v8::Object>();
Nan::Set(result, Nan::LocalString("voice_bytes_received"), Nan::New<v8::Number>(statistics.voice_bytes_received));
Nan::Set(result, Nan::LocalString("voice_bytes_send"), Nan::New<v8::Number>(statistics.voice_bytes_send));
Nan::Set(result, Nan::LocalString("control_bytes_received"), Nan::New<v8::Number>(statistics.control_bytes_received));
Nan::Set(result, Nan::LocalString("control_bytes_send"), Nan::New<v8::Number>(statistics.control_bytes_send));
info.GetReturnValue().Set(result);
} else {
info.GetReturnValue().Set(Nan::Undefined());
}
}

View File

@ -86,6 +86,7 @@ namespace tc {
static NAN_METHOD(_send_voice_data_raw);
static NAN_METHOD(_error_message);
static NAN_METHOD(_current_ping);
static NAN_METHOD(statistics);
std::unique_ptr<Nan::Callback> callback_connect;
std::unique_ptr<Nan::Callback> callback_disconnect;

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "TeaClient",
"version": "1.4.13",
"version": "1.5.0-2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {