Fixed a bug related to the file transfer
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user