Fixed a bug related to the file transfer

This commit is contained in:
WolverinDEV
2020-09-16 14:15:06 +02:00
parent 2a1f0187ac
commit 38d6ad4920
11 changed files with 674 additions and 584 deletions
+40 -26
View File
@@ -11,8 +11,8 @@
#include <include/files/Config.h>
#include "./LocalFileProvider.h"
#include "./duration_utils.h"
#include "HTTPUtils.h"
#include "LocalFileProvider.h"
#include "./HTTPUtils.h"
#include "./LocalFileTransfer.h"
#if defined(TCP_CORK) && !defined(TCP_NOPUSH)
#define TCP_NOPUSH TCP_CORK
@@ -549,6 +549,13 @@ void LocalFileTransfer::callback_transfer_network_throttle(int, short, void *ptr
void LocalFileTransfer::callback_transfer_network_read(int fd, short events, void *ptr_transfer) {
auto transfer = reinterpret_cast<FileClient*>(ptr_transfer);
std::shared_ptr<FileClient> client{};
try {
client = transfer->shared_from_this();
} catch (std::bad_weak_ptr& ex) {
logCritical(LOG_FT, "Network read worker encountered a bad weak ptr to a client. This indicated something went horribly wrong! Please submit this on https://forum.teaspeak.de !!!");
return;
}
if((unsigned) events & (unsigned) EV_TIMEOUT) {
/* should never happen, receive timeouts are done via the client tick */
@@ -569,7 +576,7 @@ void LocalFileTransfer::callback_transfer_network_read(int fd, short events, voi
if(read == 0) {
std::unique_lock slock{transfer->state_mutex};
auto original_state = transfer->state;
transfer->handle->disconnect_client(transfer->shared_from_this(), slock, true);
transfer->handle->disconnect_client(client, slock, true);
slock.unlock();
switch(original_state) {
@@ -588,7 +595,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->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::UNEXPECTED_CLIENT_DISCONNECT, "" });
transfer->handle->invoke_aborted_callback(client, { TransferError::UNEXPECTED_CLIENT_DISCONNECT, "" });
break;
}
case FileClient::STATE_FLUSHING:
@@ -607,7 +614,7 @@ void LocalFileTransfer::callback_transfer_network_read(int fd, short events, voi
std::unique_lock slock{transfer->state_mutex};
auto original_state = transfer->state;
transfer->handle->disconnect_client(transfer->shared_from_this(), slock, true);
transfer->handle->disconnect_client(client, slock, true);
slock.unlock();
switch(original_state) {
@@ -627,7 +634,7 @@ void LocalFileTransfer::callback_transfer_network_read(int fd, short events, voi
}
transfer->handle->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::NETWORK_IO_ERROR, strerror(errno) });
transfer->handle->invoke_aborted_callback(client, { TransferError::NETWORK_IO_ERROR, strerror(errno) });
break;
case FileClient::STATE_FLUSHING:
case FileClient::STATE_DISCONNECTED:
@@ -649,10 +656,10 @@ void LocalFileTransfer::callback_transfer_network_read(int fd, short events, voi
size_t bytes_buffered{0};
if(transfer->state == FileClient::STATE_AWAITING_KEY) {
bytes_buffered = transfer->handle->handle_transfer_read_raw(transfer->shared_from_this(), buffer, read);
bytes_buffered = transfer->handle->handle_transfer_read_raw(client, buffer, read);
} else if(transfer->state == FileClient::STATE_TRANSFERRING) {
if(transfer->transfer->direction == Transfer::DIRECTION_UPLOAD) {
bytes_buffered = transfer->handle->handle_transfer_read_raw(transfer->shared_from_this(), buffer, read);
bytes_buffered = transfer->handle->handle_transfer_read_raw(client, buffer, read);
} else {
debugMessage(LOG_FT, "{} Received {} bytes without any need. Dropping them.", transfer->log_prefix(), read);
}
@@ -678,6 +685,13 @@ void LocalFileTransfer::callback_transfer_network_read(int fd, short events, voi
void LocalFileTransfer::callback_transfer_network_write(int fd, short events, void *ptr_transfer) {
auto transfer = reinterpret_cast<FileClient*>(ptr_transfer);
std::shared_ptr<FileClient> client{};
try {
client = transfer->shared_from_this();
} catch (std::bad_weak_ptr& ex) {
logCritical(LOG_FT, "Network write worker encountered a bad weak ptr to a client. This indicated something went horribly wrong! Please submit this on https://forum.teaspeak.de !!!");
return;
}
if((unsigned) events & (unsigned) EV_TIMEOUT) {
if(transfer->state == FileClient::STATE_FLUSHING) {
@@ -693,11 +707,11 @@ void LocalFileTransfer::callback_transfer_network_write(int fd, short events, vo
if(!std::exchange(transfer->finished_signal_send, true)) {
if(transfer->transfer) {
transfer->handle->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::NETWORK_IO_ERROR, "failed to flush outgoing buffer" });
transfer->handle->invoke_aborted_callback(client, { TransferError::NETWORK_IO_ERROR, "failed to flush outgoing buffer" });
}
}
transfer->handle->test_disconnecting_state(transfer->shared_from_this());
transfer->handle->test_disconnecting_state(client);
return;
}
}
@@ -736,12 +750,12 @@ 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 ? transfer->transfer->expected_file_size - transfer->transfer->file_offset : -1);
transfer->handle->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::UNEXPECTED_CLIENT_DISCONNECT, "" });
transfer->handle->invoke_aborted_callback(client, { TransferError::UNEXPECTED_CLIENT_DISCONNECT, "" });
} else {
logError(LOG_FT, "{} Received network write error. Send {} bytes out of {}. Closing transfer.",
transfer->log_prefix(), transfer->statistics.file_transferred.total_bytes, transfer->transfer ? transfer->transfer->expected_file_size - transfer->transfer->file_offset : -1);
transfer->handle->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::NETWORK_IO_ERROR, strerror(errno) });
transfer->handle->invoke_aborted_callback(client, { TransferError::NETWORK_IO_ERROR, strerror(errno) });
}
} else if(transfer->state == FileClient::STATE_FLUSHING && transfer->transfer) {
{
@@ -753,12 +767,12 @@ void LocalFileTransfer::callback_transfer_network_write(int fd, short events, vo
transfer->flush_network_buffer();
if(written == 0) {
logError(LOG_FT, "{} Received unexpected client disconnect while flushing the network buffer. Transfer failed.", transfer->log_prefix());
transfer->handle->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::UNEXPECTED_CLIENT_DISCONNECT, "" });
transfer->handle->invoke_aborted_callback(client, { TransferError::UNEXPECTED_CLIENT_DISCONNECT, "" });
} else {
logError(LOG_FT, "{} Received network write error while flushing the network buffer. Closing transfer.",
transfer->log_prefix());
transfer->handle->invoke_aborted_callback(transfer->shared_from_this(), { TransferError::NETWORK_IO_ERROR, strerror(errno) });
transfer->handle->invoke_aborted_callback(client, { TransferError::NETWORK_IO_ERROR, strerror(errno) });
}
}
@@ -773,7 +787,7 @@ void LocalFileTransfer::callback_transfer_network_write(int fd, short events, vo
std::unique_lock slock{transfer->state_mutex};
/* no need to flush anything here, write will only be invoked on a client download */
transfer->handle->disconnect_client(transfer->shared_from_this(), slock, false);
transfer->handle->disconnect_client(client, slock, false);
return;
} else {
buffer->offset += written;
@@ -808,19 +822,19 @@ void LocalFileTransfer::callback_transfer_network_write(int fd, short events, vo
if(buffer_left_size > 0) {
transfer->add_network_write_event(false);
} else if(transfer->state == FileClient::STATE_FLUSHING) {
transfer->handle->test_disconnecting_state(transfer->shared_from_this());
transfer->handle->test_disconnecting_state(client);
if(!std::exchange(transfer->finished_signal_send, true)) {
if(transfer->transfer && transfer->statistics.file_transferred.total_bytes + transfer->transfer->file_offset == transfer->transfer->expected_file_size) {
logMessage(LOG_FT, "{} Finished file transfer within {}. Closing connection.", transfer->log_prefix(), duration_to_string(std::chrono::system_clock::now() - transfer->timings.key_received));
transfer->handle->report_transfer_statistics(transfer->shared_from_this());
transfer->handle->report_transfer_statistics(client);
if(auto callback{transfer->handle->callback_transfer_finished}; callback)
callback(transfer->transfer);
}
}
return;
}
transfer->handle->enqueue_disk_io(transfer->shared_from_this());
transfer->handle->enqueue_disk_io(client);
}
}
@@ -845,7 +859,7 @@ size_t LocalFileTransfer::handle_transfer_read_raw(const std::shared_ptr<FileCli
logWarning(LOG_FT, "{} Read bytes with unknown protocol. Closing connection.", client->log_prefix());
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client->shared_from_this(), slock, true);
client->handle->disconnect_client(client, slock, true);
return (size_t) -1;
}
@@ -853,7 +867,7 @@ size_t LocalFileTransfer::handle_transfer_read_raw(const std::shared_ptr<FileCli
logWarning(LOG_FT, "{} Read bytes with unknown protocol but having not awaiting key state. Closing connection.", client->log_prefix());
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client->shared_from_this(), slock, true);
client->handle->disconnect_client(client, slock, true);
return (size_t) -1;
}
@@ -923,7 +937,7 @@ size_t LocalFileTransfer::handle_transfer_read_raw(const std::shared_ptr<FileCli
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client->shared_from_this(), slock, true);
client->handle->disconnect_client(client, slock, true);
return (size_t) -1;
}
@@ -1066,7 +1080,7 @@ size_t LocalFileTransfer::handle_transfer_read(const std::shared_ptr<FileClient>
this->send_http_response(client, response);
if(response.code->code != 200 || !client->transfer) {
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client->shared_from_this(), slock, true);
client->handle->disconnect_client(client, slock, true);
return (size_t) -1;
}
@@ -1080,7 +1094,7 @@ size_t LocalFileTransfer::handle_transfer_read(const std::shared_ptr<FileClient>
logError(LOG_FT, "{} Protocol variable contains invalid protocol for awaiting key state. Disconnecting client.", client->log_prefix());
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client->shared_from_this(), slock, true);
client->handle->disconnect_client(client, slock, true);
return (size_t) -1;
}
} else if(client->state == FileClient::STATE_TRANSFERRING) {
@@ -1104,7 +1118,7 @@ size_t LocalFileTransfer::handle_transfer_read(const std::shared_ptr<FileClient>
callback(client->transfer);
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client->shared_from_this(), slock, true);
client->handle->disconnect_client(client, slock, true);
return client->network_buffer.bytes; /* a bit unexact but the best we could get away with it */
}
@@ -1144,7 +1158,7 @@ size_t LocalFileTransfer::handle_transfer_read(const std::shared_ptr<FileClient>
client->handle->send_http_response(client, response);
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client->shared_from_this(), slock, true);
client->handle->disconnect_client(client, slock, true);
return (size_t) -1;
} else if(client->networking.protocol == FileClient::PROTOCOL_TS_V1) {
@@ -1165,7 +1179,7 @@ size_t LocalFileTransfer::handle_transfer_read(const std::shared_ptr<FileClient>
callback(client->transfer);
std::unique_lock slock{client->state_mutex};
client->handle->disconnect_client(client->shared_from_this(), slock, true);
client->handle->disconnect_client(client, slock, true);
return (size_t) -1;
}