Added file transfer status
This commit is contained in:
parent
1a3235697e
commit
b987583770
@ -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 */
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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 */);
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
@ -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&);
|
||||
};
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user