Added file transfer status

This commit is contained in:
WolverinDEV 2020-05-13 18:03:14 +02:00
parent 1a3235697e
commit b987583770
11 changed files with 225 additions and 81 deletions

View File

@ -345,8 +345,8 @@ namespace ts::server::file {
std::function<void(const std::shared_ptr<Transfer>&)> callback_transfer_registered{}; /* transfer has been registered */
std::function<void(const std::shared_ptr<Transfer>&)> callback_transfer_started{}; /* transfer has been started */
std::function<void(const std::shared_ptr<Transfer>&)> callback_transfer_finished{}; /* transfer has been finished */
std::function<void(const std::shared_ptr<Transfer>&, const TransferError&)> callback_transfer_aborted{}; /* an error happened while transferring the data */
std::function<void(const std::shared_ptr<Transfer>&, const TransferStatistics&)> callback_transfer_statistics{};
std::function<void(const std::shared_ptr<Transfer>&, const transfer::TransferStatistics&, const TransferError&)> callback_transfer_aborted{}; /* an error happened while transferring the data */
};
}

View File

@ -458,7 +458,6 @@ namespace ts::server::file {
void enqueue_disk_io(const std::shared_ptr<FileClient>& /* client */);
void execute_disk_io(const std::shared_ptr<FileClient>& /* client */);
void report_transfer_statistics(const std::shared_ptr<FileClient>& /* client */);
[[nodiscard]] TransferUploadRawResult handle_transfer_upload_raw(const std::shared_ptr<FileClient>& /* client */, const char * /* buffer */, size_t /* length */);
[[nodiscard]] TransferUploadHTTPResult handle_transfer_upload_http(const std::shared_ptr<FileClient>& /* client */, const char * /* buffer */, size_t /* length */);
@ -473,6 +472,11 @@ namespace ts::server::file {
static void dispatch_loop_network(void*);
static void dispatch_loop_disk_io(void*);
void report_transfer_statistics(const std::shared_ptr<FileClient>& /* client */);
[[nodiscard]] TransferStatistics generate_transfer_statistics_report(const std::shared_ptr<FileClient>& /* client */);
void invoke_aborted_callback(const std::shared_ptr<FileClient>& /* client */, const TransferError& /* error */);
void invoke_aborted_callback(const std::shared_ptr<Transfer>& /* pending transfer */, const TransferError& /* error */);
size_t handle_transfer_read(const std::shared_ptr<FileClient>& /* client */, const char* /* buffer */, size_t /* bytes */);
size_t handle_transfer_read_raw(const std::shared_ptr<FileClient>& /* client */, const char* /* buffer */, size_t /* bytes */);
[[nodiscard]] TransferKeyApplyResult handle_transfer_key_provided(const std::shared_ptr<FileClient>& /* client */, std::string& /* error */);

View File

@ -88,7 +88,7 @@ void LocalFileTransfer::dispatch_loop_client_worker(void *ptr_transfer) {
while(provider->disconnect.active) {
{
std::unique_lock dlock{provider->disconnect.mutex};
provider->disconnect.notify_cv.wait_for(dlock, std::chrono::seconds{1});
provider->disconnect.notify_cv.wait_for(dlock, std::chrono::milliseconds {500}); /* report all 500ms the statistics */
}
/* run the disconnect worker at least once before exiting */
@ -123,17 +123,15 @@ void LocalFileTransfer::dispatch_loop_client_worker(void *ptr_transfer) {
auto now = std::chrono::system_clock::now();
std::copy_if(provider->pending_transfers.begin(), provider->pending_transfers.end(), std::back_inserter(timeouted_transfers), [&](const std::shared_ptr<Transfer>& t) {
return t->initialized_timestamp + std::chrono::seconds{100} < now; //FIXME: Decrease to 10 again!
return t->initialized_timestamp + std::chrono::seconds{10} < now;
});
provider->pending_transfers.erase(std::remove_if(provider->pending_transfers.begin(), provider->pending_transfers.end(), [&](const auto& t) {
return std::find(timeouted_transfers.begin(), timeouted_transfers.end(), t) != timeouted_transfers.end();
}), provider->pending_transfers.end());
}
for(const auto& pt : timeouted_transfers) {
if(auto callback{provider->callback_transfer_aborted}; callback)
callback(pt, { TransferError::TRANSFER_TIMEOUT, "" });
}
for(const auto& pt : timeouted_transfers)
provider->invoke_aborted_callback(pt, { TransferError::TRANSFER_TIMEOUT, "" });
if(!timeouted_transfers.empty())
logMessage(LOG_FT, "Removed {} pending transfers because no request has been made for them.", timeouted_transfers.size());
@ -155,7 +153,6 @@ void LocalFileTransfer::dispatch_loop_client_worker(void *ptr_transfer) {
} else if(t->state == FileClient::STATE_TRANSFERRING) {
assert(t->transfer);
if(t->transfer->direction == Transfer::DIRECTION_UPLOAD) {
return false; //FIXME: Due to debugging reasons
return t->timings.last_read + std::chrono::seconds{5} < now;
} else if(t->transfer->direction == Transfer::DIRECTION_DOWNLOAD) {
return t->timings.last_write + std::chrono::seconds{5} < now;
@ -179,8 +176,7 @@ void LocalFileTransfer::dispatch_loop_client_worker(void *ptr_transfer) {
break;
case FileClient::STATE_TRANSFERRING:
logMessage(LOG_FT, "{} Networking timeout. Dropping client", client->log_prefix());
if(auto callback{provider->callback_transfer_aborted}; callback)
callback(client->transfer, { TransferError::TRANSFER_TIMEOUT, "" });
provider->invoke_aborted_callback(client, { TransferError::TRANSFER_TIMEOUT, "" });
break;
case FileClient::STATE_DISCONNECTING:
logMessage(LOG_FT, "{} Failed to flush connection. Dropping client", client->log_prefix());
@ -207,6 +203,10 @@ void LocalFileTransfer::report_transfer_statistics(const std::shared_ptr<FileCli
auto callback{this->callback_transfer_statistics};
if(!callback) return;
callback(client->transfer, this->generate_transfer_statistics_report(client));
}
TransferStatistics LocalFileTransfer::generate_transfer_statistics_report(const std::shared_ptr<FileClient> &client) {
TransferStatistics stats{};
stats.network_bytes_send = client->statistics.network_send.total_bytes;
@ -221,6 +221,36 @@ void LocalFileTransfer::report_transfer_statistics(const std::shared_ptr<FileCli
stats.file_start_offset = client->transfer->file_offset;
stats.file_current_offset = client->statistics.file_transferred.total_bytes + client->transfer->file_offset;
stats.file_total_size = client->transfer->expected_file_size;
return stats;
}
callback(client->transfer, stats);
void LocalFileTransfer::invoke_aborted_callback(const std::shared_ptr<FileClient> &client,
const ts::server::file::transfer::TransferError &error) {
auto callback{this->callback_transfer_aborted};
if(!callback) return;
callback(client->transfer, this->generate_transfer_statistics_report(client), error);
}
void LocalFileTransfer::invoke_aborted_callback(const std::shared_ptr<Transfer> &transfer,
const ts::server::file::transfer::TransferError &error) {
auto callback{this->callback_transfer_aborted};
if(!callback) return;
TransferStatistics stats{};
stats.network_bytes_send = 0;
stats.network_bytes_received = 0;
stats.file_bytes_transferred = 0;
stats.delta_network_bytes_received = 0;
stats.delta_network_bytes_send = 0;
stats.delta_file_bytes_transferred = 0;
stats.file_start_offset = transfer->file_offset;
stats.file_current_offset = transfer->file_offset;
stats.file_total_size = transfer->expected_file_size;
callback(transfer, stats, error);
}

View File

@ -336,10 +336,8 @@ void LocalFileTransfer::execute_disk_io(const std::shared_ptr<FileClient> &clien
logError(LOG_FT, "{} Received unexpected file write EOF. EOF received at {} but expected {}. Actual file offset: {}. Closing transfer.",
client->log_prefix(), offset_written, client->transfer->expected_file_size, aoffset);
this->report_transfer_statistics(client);
if(auto callback{client->handle->callback_transfer_aborted}; callback)
callback(client->transfer, { TransferError::UNEXPECTED_DISK_EOF, strerror(errno) });
this->invoke_aborted_callback(client, { TransferError::UNEXPECTED_DISK_EOF, strerror(errno) });
{
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client, slock, true);
@ -356,10 +354,7 @@ void LocalFileTransfer::execute_disk_io(const std::shared_ptr<FileClient> &clien
logError(LOG_FT, "{} Received write to disk IO error. Write pointer is at {} of {}. Actual file offset: {}. Closing transfer.",
client->log_prefix(), offset_written, client->transfer->expected_file_size, aoffset);
this->report_transfer_statistics(client);
if(auto callback{client->handle->callback_transfer_aborted}; callback)
callback(client->transfer, { TransferError::DISK_IO_ERROR, strerror(errno) });
this->invoke_aborted_callback(client, { TransferError::DISK_IO_ERROR, strerror(errno) });
{
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client, slock, true);
@ -429,9 +424,7 @@ void LocalFileTransfer::execute_disk_io(const std::shared_ptr<FileClient> &clien
logError(LOG_FT, "{} Received unexpected read EOF. EOF received at {} but expected {}. Actual file offset: {}. Disconnecting client.",
client->log_prefix(), offset_send, client->transfer->expected_file_size, aoffset);
this->report_transfer_statistics(client);
if(auto callback{client->handle->callback_transfer_aborted}; callback)
callback(client->transfer, { TransferError::UNEXPECTED_DISK_EOF, strerror(errno) });
this->invoke_aborted_callback(client, { TransferError::UNEXPECTED_DISK_EOF, "" });
}
{
@ -446,10 +439,7 @@ void LocalFileTransfer::execute_disk_io(const std::shared_ptr<FileClient> &clien
logWarning(LOG_FT, "{} Failed to read from file {} ({}/{}). Aborting transfer.", client->log_prefix(), client->transfer->absolute_file_path, errno, strerror(errno));
this->report_transfer_statistics(client);
if(auto callback{client->handle->callback_transfer_aborted}; callback)
callback(client->transfer, { TransferError::DISK_IO_ERROR, strerror(errno) });
this->invoke_aborted_callback(client, { TransferError::DISK_IO_ERROR, strerror(errno) });
{
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client, slock, true);

View File

@ -478,9 +478,7 @@ void LocalFileTransfer::callback_transfer_network_read(int fd, short events, voi
transfer->log_prefix(), transfer->statistics.file_transferred.total_bytes, transfer->transfer->expected_file_size - transfer->transfer->file_offset);
}
transfer->handle->report_transfer_statistics(transfer->shared_from_this());
if(auto callback{transfer->handle->callback_transfer_aborted}; callback)
callback(transfer->transfer, { TransferError::UNEXPECTED_CLIENT_DISCONNECT, "" });
transfer->handle->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::UNEXPECTED_CLIENT_DISCONNECT, "" });
break;
}
case FileClient::STATE_DISCONNECTING:
@ -515,9 +513,8 @@ void LocalFileTransfer::callback_transfer_network_read(int fd, short events, voi
transfer->log_prefix(), transfer->statistics.file_transferred.total_bytes, transfer->transfer->expected_file_size - transfer->transfer->file_offset, errno, strerror(errno));
}
transfer->handle->report_transfer_statistics(transfer->shared_from_this());
if(auto callback{transfer->handle->callback_transfer_aborted}; callback)
callback(transfer->transfer, { TransferError::NETWORK_IO_ERROR, strerror(errno) });
transfer->handle->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::NETWORK_IO_ERROR, strerror(errno) });
break;
case FileClient::STATE_DISCONNECTING:
case FileClient::STATE_DISCONNECTED:
@ -623,10 +620,7 @@ void LocalFileTransfer::callback_transfer_network_write(int fd, short events, vo
logError(LOG_FT, "{} Client disconnected unexpectedly on write. Send {} bytes out of {}.",
transfer->log_prefix(), transfer->statistics.file_transferred.total_bytes, transfer->transfer->expected_file_size - transfer->transfer->file_offset);
transfer->handle->report_transfer_statistics(transfer->shared_from_this());
if(auto callback{transfer->handle->callback_transfer_aborted}; callback)
callback(transfer->transfer, { TransferError::UNEXPECTED_CLIENT_DISCONNECT, strerror(errno) });
transfer->handle->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::UNEXPECTED_CLIENT_DISCONNECT, "" });
{
std::unique_lock slock{transfer->state_mutex};
transfer->handle->disconnect_client(transfer->shared_from_this(), slock, true);
@ -640,10 +634,7 @@ void LocalFileTransfer::callback_transfer_network_write(int fd, short events, vo
logError(LOG_FT, "{} Received network write error. Send {} bytes out of {}. Closing transfer.",
transfer->log_prefix(), transfer->statistics.file_transferred.total_bytes, transfer->transfer->expected_file_size - transfer->transfer->file_offset);
transfer->handle->report_transfer_statistics(transfer->shared_from_this());
if(auto callback{transfer->handle->callback_transfer_aborted}; callback)
callback(transfer->transfer, { TransferError::NETWORK_IO_ERROR, strerror(errno) });
transfer->handle->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::NETWORK_IO_ERROR, strerror(errno) });
{
std::unique_lock slock{transfer->state_mutex};
transfer->handle->disconnect_client(transfer->shared_from_this(), slock, false);
@ -780,20 +771,14 @@ size_t LocalFileTransfer::handle_transfer_read_raw(const std::shared_ptr<FileCli
case TransferKeyApplyResult::FILE_ERROR:
assert(client->transfer);
this->report_transfer_statistics(client);
if(auto callback{this->callback_transfer_aborted}; callback)
callback(client->transfer, { TransferError::DISK_INITIALIZE_ERROR, error_detail });
this->invoke_aborted_callback(client, { TransferError::DISK_INITIALIZE_ERROR, error_detail });
logMessage(LOG_FT, "{} Disconnecting client because we failed to open the target file.", client->log_prefix());
break;
case TransferKeyApplyResult::INTERNAL_ERROR:
default:
this->report_transfer_statistics(client);
if(auto callback{this->callback_transfer_aborted}; client->transfer && callback)
callback(client->transfer, { TransferError::UNKNOWN, error_detail });
this->invoke_aborted_callback(client, { TransferError::UNKNOWN, error_detail });
logMessage(LOG_FT, "{} Disconnecting client because of an unknown key initialize error ({}).", client->log_prefix(), (int) key_result);
break;
}
@ -872,10 +857,7 @@ size_t LocalFileTransfer::handle_transfer_read(const std::shared_ptr<FileClient>
case TransferKeyApplyResult::FILE_ERROR:
assert(client->transfer);
this->report_transfer_statistics(client);
if(auto callback{this->callback_transfer_aborted}; callback)
callback(client->transfer, { TransferError::DISK_INITIALIZE_ERROR, error_detail });
this->invoke_aborted_callback(client, { TransferError::DISK_INITIALIZE_ERROR, error_detail });
logMessage(LOG_FT, "{} Disconnecting client because we failed to open the target file.", client->log_prefix());
response.code = http::code::code(500, "Internal Server Error");
response.setHeader("x-error-message", { error_detail });
@ -889,10 +871,7 @@ size_t LocalFileTransfer::handle_transfer_read(const std::shared_ptr<FileClient>
case TransferKeyApplyResult::INTERNAL_ERROR:
default:
this->report_transfer_statistics(client);
if(auto callback{this->callback_transfer_aborted}; client->transfer && callback)
callback(client->transfer, { TransferError::UNKNOWN, error_detail });
this->invoke_aborted_callback(client, { TransferError::UNKNOWN, error_detail });
logMessage(LOG_FT, "{} Disconnecting client because of an unknown key initialize error ({}).", client->log_prefix(), (int) key_result);
response.code = http::code::code(500, "Internal Server Error");
response.setHeader("x-error-message", { error_detail.empty() ? "failed to initialize transfer" : error_detail });

@ -1 +1 @@
Subproject commit a8a0aabd7fca05b950de9f781a3cd6ba5b799f79
Subproject commit be826ccb507a84d97c9c07397b05a8fe731f7ce5

View File

@ -4,10 +4,14 @@
#include <files/FileServer.h>
#include <log/LogUtils.h>
#include "./client/ConnectedClient.h"
#include "FileServerHandler.h"
using namespace ts::server::file;
FileServerHandler::FileServerHandler(ts::server::InstanceHandler *instance) : instance_{instance} {}
bool FileServerHandler::initialize(std::string &error) {
/*
* FIXME: Ports etc!
@ -15,7 +19,6 @@ bool FileServerHandler::initialize(std::string &error) {
auto bindings_string = this->properties()[property::SERVERINSTANCE_FILETRANSFER_HOST].as<string>();
auto port = this->properties()[property::SERVERINSTANCE_FILETRANSFER_PORT].as<uint16_t>();
*/
/* TODO: Callback handler */
if(!file::initialize(error))
return false;
@ -27,24 +30,170 @@ bool FileServerHandler::initialize(std::string &error) {
transfer.callback_transfer_started = std::bind(&FileServerHandler::callback_transfer_started, this, std::placeholders::_1);
transfer.callback_transfer_finished = std::bind(&FileServerHandler::callback_transfer_finished, this, std::placeholders::_1);
transfer.callback_transfer_aborted = std::bind(&FileServerHandler::callback_transfer_aborted, this, std::placeholders::_1, std::placeholders::_2);
transfer.callback_transfer_aborted = std::bind(&FileServerHandler::callback_transfer_aborted, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
transfer.callback_transfer_statistics = std::bind(&FileServerHandler::callback_transfer_statistics, this, std::placeholders::_1, std::placeholders::_2);
return true;
}
void FileServerHandler::finalize() {
file::finalize();
}
void FileServerHandler::callback_transfer_registered(const std::shared_ptr<transfer::Transfer> &transfer) {
auto server = this->instance_->getVoiceServerManager()->findServerById(transfer->server->server_id());
if(!server) return; /* well that's bad */
const auto bytes = transfer->expected_file_size - transfer->file_offset;
if(transfer->direction == transfer::Transfer::DIRECTION_UPLOAD) {
server->properties()[property::VIRTUALSERVER_TOTAL_BYTES_UPLOADED] += transfer->expected_file_size - transfer->file_offset;
server->properties()[property::VIRTUALSERVER_MONTH_BYTES_UPLOADED] += transfer->expected_file_size - transfer->file_offset;
server->properties()[property::VIRTUALSERVER_TOTAL_BYTES_UPLOADED] += bytes;
server->properties()[property::VIRTUALSERVER_MONTH_BYTES_UPLOADED] += bytes;
} else {
server->properties()[property::VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED] += transfer->expected_file_size - transfer->file_offset;
server->properties()[property::VIRTUALSERVER_MONTH_BYTES_DOWNLOADED] += transfer->expected_file_size - transfer->file_offset;
server->properties()[property::VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED] += bytes;
server->properties()[property::VIRTUALSERVER_MONTH_BYTES_DOWNLOADED] += bytes;
}
auto client = server->find_client_by_id(transfer->client_id);
if(client && client->getUid() == transfer->client_unique_id) {
if(transfer->direction == transfer::Transfer::DIRECTION_UPLOAD) {
client->properties()[property::CLIENT_TOTAL_BYTES_UPLOADED] += bytes;
client->properties()[property::CLIENT_MONTH_BYTES_UPLOADED] += bytes;
} else {
client->properties()[property::CLIENT_MONTH_BYTES_DOWNLOADED] += bytes;
client->properties()[property::CLIENT_MONTH_BYTES_DOWNLOADED] += bytes;
}
}
}
void FileServerHandler::callback_transfer_aborted(const std::shared_ptr<transfer::Transfer> &transfer,
const transfer::TransferStatistics &statistics,
const ts::server::file::transfer::TransferError &error) {
/* TODO: Remove not used quota from server & client */
auto server = this->instance_->getVoiceServerManager()->findServerById(transfer->server->server_id());
if(!server) return; /* well that's bad */
if(statistics.file_total_size < statistics.file_current_offset)
return;
const int64_t bytes_left = statistics.file_total_size - statistics.file_current_offset;
if(transfer->direction == transfer::Transfer::DIRECTION_UPLOAD) {
server->properties()[property::VIRTUALSERVER_TOTAL_BYTES_UPLOADED] += -bytes_left;
server->properties()[property::VIRTUALSERVER_MONTH_BYTES_UPLOADED] += -bytes_left;
} else {
server->properties()[property::VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED] += -bytes_left;
server->properties()[property::VIRTUALSERVER_MONTH_BYTES_DOWNLOADED] += -bytes_left;
}
auto client = server->find_client_by_id(transfer->client_id);
if(client && client->getUid() == transfer->client_unique_id) {
if(transfer->direction == transfer::Transfer::DIRECTION_UPLOAD) {
client->properties()[property::CLIENT_TOTAL_BYTES_UPLOADED] += -bytes_left;
client->properties()[property::CLIENT_MONTH_BYTES_UPLOADED] += -bytes_left;
} else {
client->properties()[property::CLIENT_MONTH_BYTES_DOWNLOADED] += -bytes_left;
client->properties()[property::CLIENT_MONTH_BYTES_DOWNLOADED] += -bytes_left;
}
//notifystatusfiletransfer clientftfid=4096 status=2568 failed_permid=234 msg=insufficient\sclient\spermissions\s(failed\son\si_ft_needed_file_upload_power) size=0
ts::command_builder notify{"notifystatusfiletransfer"};
notify.put_unchecked(0, "clientftfid", transfer->client_transfer_id);
notify.put(0, "size", 0); /* not sure where TeamSpeak counts from */
using ErrorType = ts::server::file::transfer::TransferError::Type;
switch (error.error_type) {
case ErrorType::TRANSFER_TIMEOUT:
notify.put_unchecked(0, "status", (int) error::file_transfer_connection_timeout);
notify.put_unchecked(0, "msg", findError(error::file_transfer_connection_timeout).message);
break;
case ErrorType::DISK_IO_ERROR:
case ErrorType::DISK_TIMEOUT:
case ErrorType::DISK_INITIALIZE_ERROR:
notify.put_unchecked(0, "status", (int) error::file_io_error);
notify.put_unchecked(0, "msg", findError(error::file_io_error).message);
break;
case ErrorType::UNKNOWN:
case ErrorType::NETWORK_IO_ERROR:
notify.put_unchecked(0, "status", (int) error::file_connection_lost);
notify.put_unchecked(0, "msg", findError(error::file_connection_lost).message);
break;
case ErrorType::UNEXPECTED_CLIENT_DISCONNECT:
case ErrorType::UNEXPECTED_DISK_EOF:
notify.put_unchecked(0, "status", (int) error::file_transfer_interrupted);
notify.put_unchecked(0, "msg", findError(error::file_transfer_interrupted).message);
break;
}
notify.put_unchecked(0, "extra_msg", error.error_message);
client->sendCommand(notify);
}
}
void FileServerHandler::callback_transfer_statistics(const std::shared_ptr<transfer::Transfer> &transfer,
const ts::server::file::transfer::TransferStatistics &statistics) {
auto server = this->instance_->getVoiceServerManager()->findServerById(transfer->server->server_id());
if(!server) return; /* well that's bad */
auto client = server->find_client_by_id(transfer->client_id);
if(!client || client->getUid() != transfer->client_unique_id) {
/* client not online anymore, but we could still log this as server traffic */
if(transfer->direction == transfer::Transfer::DIRECTION_UPLOAD) {
server->getServerStatistics()->logFileTransferIn(statistics.delta_file_bytes_transferred);
} else {
server->getServerStatistics()->logFileTransferOut(statistics.delta_file_bytes_transferred);
}
return;
}
if(transfer->direction == transfer::Transfer::DIRECTION_UPLOAD) {
client->getConnectionStatistics()->logFileTransferIn(statistics.delta_file_bytes_transferred);
} else {
client->getConnectionStatistics()->logFileTransferOut(statistics.delta_file_bytes_transferred);
}
ts::command_builder notify{"notifyfiletransferprogress"};
notify.put_unchecked(0, "clientftid", transfer->client_transfer_id);
notify.put_unchecked(0, "file_bytes_transferred", statistics.file_bytes_transferred);
notify.put_unchecked(0, "network_bytes_send", statistics.network_bytes_send);
notify.put_unchecked(0, "network_bytes_received", statistics.network_bytes_received);
notify.put_unchecked(0, "file_start_offset", statistics.file_start_offset);
notify.put_unchecked(0, "file_current_offset", statistics.file_current_offset);
notify.put_unchecked(0, "file_total_size", statistics.file_total_size);
client->sendCommand(notify);
}
void FileServerHandler::callback_transfer_started(const std::shared_ptr<transfer::Transfer> &transfer) {
auto server = this->instance_->getVoiceServerManager()->findServerById(transfer->server->server_id());
if(!server) return; /* well that's bad */
auto client = server->find_client_by_id(transfer->client_id);
if(!client || client->getUid() != transfer->client_unique_id) return;
ts::command_builder notify{"notifyfiletransferstarted"};
notify.put_unchecked(0, "clientftid", transfer->client_transfer_id);
client->sendCommand(notify);
}
void FileServerHandler::callback_transfer_finished(const std::shared_ptr<transfer::Transfer> &transfer) {
auto server = this->instance_->getVoiceServerManager()->findServerById(transfer->server->server_id());
if(!server) return; /* well that's bad */
auto client = server->find_client_by_id(transfer->client_id);
if(!client || client->getUid() != transfer->client_unique_id) return;
ts::command_builder notify{"notifystatusfiletransfer"};
notify.put_unchecked(0, "clientftfid", transfer->client_transfer_id);
notify.put(0, "size", 0); /* not sure where TeamSpeak counts from */
notify.put_unchecked(0, "status", (int) error::file_transfer_complete);
notify.put_unchecked(0, "msg", findError(error::file_transfer_complete).message);
/* TODO: Some stats? */
client->sendCommand(notify);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <files/FileServer.h>
#include "./InstanceHandler.h"
@ -25,7 +26,7 @@ namespace ts::server::file {
void callback_transfer_started(const std::shared_ptr<transfer::Transfer>&);
void callback_transfer_finished(const std::shared_ptr<transfer::Transfer>&);
void callback_transfer_aborted(const std::shared_ptr<transfer::Transfer>&, const transfer::TransferError&);
void callback_transfer_aborted(const std::shared_ptr<transfer::Transfer>&, const transfer::TransferStatistics&, const transfer::TransferError&);
void callback_transfer_statistics(const std::shared_ptr<transfer::Transfer>&, const transfer::TransferStatistics&);
};
}

View File

@ -428,6 +428,11 @@ void InstanceHandler::stopInstance() {
this->save_channel_permissions();
this->save_group_permissions();
if(this->file_server_handler_) {
this->file_server_handler_->finalize();
delete std::exchange(this->file_server_handler_, nullptr);
}
delete this->sslMgr;
this->sslMgr = nullptr;

View File

@ -209,20 +209,6 @@ void VirtualServer::executeServerTick() {
BEGIN_TIMINGS();
this->serverStatistics->tick();
if(fileStatisticsTimestamp + seconds(5) < system_clock::now()) {
fileStatisticsTimestamp = system_clock::now();
auto update = this->serverStatistics->mark_file_bytes();
if(update.first > 0) {
this->properties()[property::VIRTUALSERVER_MONTH_BYTES_DOWNLOADED] += update.first;
this->properties()[property::VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED] += update.first;
}
if(update.second > 0) {
this->properties()[property::VIRTUALSERVER_MONTH_BYTES_UPLOADED] += update.second;
this->properties()[property::VIRTUALSERVER_TOTAL_BYTES_UPLOADED] += update.second;
}
}
{
lock_guard<threads::Mutex> lock(this->join_attempts_lock);
if(system_clock::now() > this->join_last_decrease + seconds(5)) {

View File

@ -782,8 +782,8 @@ command_result QueryClient::handleCommandHostInfo(Command &) {
res["connection_bandwidth_received_last_minute_total"] = std::accumulate(report_minute.connection_bytes_received.begin(), report_minute.connection_bytes_received.end(), 0U);
res["connection_filetransfer_bandwidth_sent"] = report_minute.file_bytes_sent;
res["connection_filetransfer_bandwidth_received"] = report_minute.file_bytes_received;
res["connection_filetransfer_bandwidth_sent"] = report_second.file_bytes_sent;
res["connection_filetransfer_bandwidth_received"] = report_second.file_bytes_received;
res["connection_filetransfer_bytes_sent_total"] = total_stats.file_bytes_sent;
res["connection_filetransfer_bytes_received_total"] = total_stats.file_bytes_received;