File transfer server now respects the port and host settings set via the config.yml
This commit is contained in:
@@ -168,95 +168,161 @@ void FileClient::flush_network_buffer() {
|
||||
}
|
||||
|
||||
NetworkingStartResult LocalFileTransfer::start_networking() {
|
||||
std::lock_guard nlock{this->network.mutex};
|
||||
assert(!this->network.active);
|
||||
|
||||
this->network.active = true;
|
||||
this->network.event_base = event_base_new();
|
||||
if(!this->network.event_base) return NetworkingStartResult::OUT_OF_MEMORY;
|
||||
|
||||
bool bound{false};
|
||||
for(auto& binding : this->network.bindings) {
|
||||
binding->file_descriptor = socket(binding->address.ss_family, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
||||
if(!binding->file_descriptor) {
|
||||
logWarning(LOG_FT, "Failed to allocate socket for {}: {}/{}", binding->hostname, errno, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int enable = 1, disabled = 0;
|
||||
|
||||
if (setsockopt(binding->file_descriptor, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
|
||||
logWarning(LOG_FT, "Failed to activate SO_REUSEADDR for binding {} ({} | {})", binding->hostname, errno, strerror(errno));
|
||||
|
||||
if(setsockopt(binding->file_descriptor, IPPROTO_TCP, TCP_NOPUSH, &disabled, sizeof disabled) < 0)
|
||||
logWarning(LOG_FT, "Failed to deactivate TCP_NOPUSH for binding {} ({} | {})", binding->hostname, errno, strerror(errno));
|
||||
|
||||
if(binding->address.ss_family == AF_INET6) {
|
||||
if(setsockopt(binding->file_descriptor, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(int)) < 0)
|
||||
logWarning(LOG_FT, "Failed to activate IPV6_V6ONLY for IPv6 binding {} ({} | {})", binding->hostname, errno, strerror(errno));
|
||||
}
|
||||
if(fcntl(binding->file_descriptor, F_SETFD, FD_CLOEXEC) < 0)
|
||||
logWarning(LOG_FT, "Failed to set flag FD_CLOEXEC for binding {} ({} | {})", binding->hostname, errno, strerror(errno));
|
||||
|
||||
|
||||
if (bind(binding->file_descriptor, (struct sockaddr *) &binding->address, sizeof(binding->address)) < 0) {
|
||||
logError(LOG_FT, "Failed to bind server to {}. (Failed to bind socket: {} | {})", binding->hostname, errno, strerror(errno));
|
||||
goto reset_binding;
|
||||
}
|
||||
|
||||
if (listen(binding->file_descriptor, 8) < 0) {
|
||||
logError(LOG_FT, "Failed to bind server to {}. (Failed to listen: {} | {})", binding->hostname, errno, strerror(errno));
|
||||
goto reset_binding;
|
||||
}
|
||||
|
||||
binding->handle = this;
|
||||
binding->accept_event = event_new(this->network.event_base, binding->file_descriptor, (unsigned) EV_READ | (unsigned) EV_PERSIST, &LocalFileTransfer::callback_transfer_network_accept, &*binding);
|
||||
if(!binding->accept_event)
|
||||
goto reset_binding;
|
||||
|
||||
event_add(binding->accept_event, nullptr);
|
||||
logMessage(LOG_FT, "Started to listen on {}:{}", binding->hostname, net::port(binding->address));
|
||||
|
||||
bound = true;
|
||||
continue;
|
||||
|
||||
reset_binding:
|
||||
if(binding->accept_event) {
|
||||
event_free(binding->accept_event);
|
||||
binding->accept_event = nullptr;
|
||||
}
|
||||
|
||||
if(binding->file_descriptor > 0)
|
||||
::close(binding->file_descriptor);
|
||||
binding->file_descriptor = 0;
|
||||
|
||||
binding->handle = nullptr;
|
||||
}
|
||||
if(!bound) {
|
||||
event_base_free(std::exchange(this->network.event_base, nullptr));
|
||||
return NetworkingStartResult::NO_BINDINGS;
|
||||
}
|
||||
|
||||
this->network.dispatch_thread = std::thread(&LocalFileTransfer::dispatch_loop_network, this);
|
||||
return NetworkingStartResult::SUCCESS;
|
||||
}
|
||||
|
||||
void LocalFileTransfer::shutdown_networking() {
|
||||
if(!this->network.active) return;
|
||||
this->network.active = false;
|
||||
NetworkingBindResult LocalFileTransfer::add_network_binding(const NetworkBinding &binding) {
|
||||
std::lock_guard nlock{this->network.mutex};
|
||||
if(!this->network.active)
|
||||
return NetworkingBindResult::NETWORKING_NOT_INITIALIZED;
|
||||
|
||||
for(auto& binding : this->network.bindings) {
|
||||
if(binding->accept_event) {
|
||||
event_del_block(binding->accept_event);
|
||||
event_free(binding->accept_event);
|
||||
binding->accept_event = nullptr;
|
||||
for(const auto& abinding : this->network.bindings) {
|
||||
if(net::address_equal(abinding->address, binding.address) && net::port(abinding->address) == net::port(binding.address))
|
||||
return NetworkingBindResult::BINDING_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
NetworkingBindResult result{NetworkingBindResult::SUCCESS};
|
||||
auto abinding = std::make_shared<ActiveNetworkBinding>();
|
||||
abinding->handle = this;
|
||||
abinding->hostname = binding.hostname;
|
||||
memcpy(&abinding->address, &binding.address, sizeof(binding.address));
|
||||
|
||||
abinding->file_descriptor = socket(abinding->address.ss_family, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
||||
if(!abinding->file_descriptor) {
|
||||
//logWarning(LOG_FT, "Failed to allocate socket for {}: {}/{}", abinding->hostname, errno, strerror(errno));
|
||||
return NetworkingBindResult::FAILED_TO_ALLOCATE_SOCKET;
|
||||
}
|
||||
|
||||
|
||||
int enable = 1, disabled = 0;
|
||||
|
||||
if (setsockopt(abinding->file_descriptor, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
|
||||
logWarning(LOG_FT, "Failed to activate SO_REUSEADDR for binding {} ({}/{})", abinding->hostname, errno, strerror(errno));
|
||||
|
||||
if(setsockopt(abinding->file_descriptor, IPPROTO_TCP, TCP_NOPUSH, &disabled, sizeof disabled) < 0)
|
||||
logWarning(LOG_FT, "Failed to deactivate TCP_NOPUSH for binding {} ({}/{})", abinding->hostname, errno, strerror(errno));
|
||||
|
||||
if(abinding->address.ss_family == AF_INET6) {
|
||||
if(setsockopt(abinding->file_descriptor, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(int)) < 0)
|
||||
logWarning(LOG_FT, "Failed to activate IPV6_V6ONLY for IPv6 binding {} ({}/{})", abinding->hostname, errno, strerror(errno));
|
||||
}
|
||||
if(fcntl(abinding->file_descriptor, F_SETFD, FD_CLOEXEC) < 0)
|
||||
logWarning(LOG_FT, "Failed to set flag FD_CLOEXEC for binding {} ({}/{})", abinding->hostname, errno, strerror(errno));
|
||||
|
||||
|
||||
if (bind(abinding->file_descriptor, (struct sockaddr *) &abinding->address, sizeof(abinding->address)) < 0) {
|
||||
//logError(LOG_FT, "Failed to bind server to {}. (Failed to bind socket: {}/{})", binding->hostname, errno, strerror(errno));
|
||||
result = NetworkingBindResult::FAILED_TO_BIND;
|
||||
goto reset_binding;
|
||||
}
|
||||
|
||||
if (listen(abinding->file_descriptor, 8) < 0) {
|
||||
//logError(LOG_FT, "Failed to bind server to {}. (Failed to listen: {}/{})", binding->hostname, errno, strerror(errno));
|
||||
result = NetworkingBindResult::FAILED_TO_LISTEN;
|
||||
goto reset_binding;
|
||||
}
|
||||
|
||||
abinding->accept_event = event_new(this->network.event_base, abinding->file_descriptor, (unsigned) EV_READ | (unsigned) EV_PERSIST, &LocalFileTransfer::callback_transfer_network_accept, &*abinding);
|
||||
if(!abinding->accept_event) {
|
||||
result = NetworkingBindResult::OUT_OF_MEMORY;
|
||||
goto reset_binding;
|
||||
}
|
||||
|
||||
event_add(abinding->accept_event, nullptr);
|
||||
logMessage(LOG_FT, "Started to listen on {}:{}", abinding->hostname, net::port(abinding->address));
|
||||
this->network.bindings.push_back(std::move(abinding));
|
||||
|
||||
return NetworkingBindResult::SUCCESS;
|
||||
|
||||
reset_binding:
|
||||
if(abinding->accept_event) {
|
||||
event_free(abinding->accept_event);
|
||||
abinding->accept_event = nullptr;
|
||||
}
|
||||
|
||||
if(abinding->file_descriptor > 0)
|
||||
::close(abinding->file_descriptor);
|
||||
abinding->file_descriptor = 0;
|
||||
abinding->handle = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<NetworkBinding> LocalFileTransfer::active_network_bindings() {
|
||||
std::lock_guard nlock{this->network.mutex};
|
||||
std::vector<NetworkBinding> result{};
|
||||
result.reserve(this->network.bindings.size());
|
||||
|
||||
for(const auto& binding : this->network.bindings) {
|
||||
auto& rbinding = result.emplace_back();
|
||||
rbinding.hostname = binding->hostname;
|
||||
memcpy(&rbinding.address, &binding->address, sizeof(rbinding.address));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NetworkingUnbindResult LocalFileTransfer::remove_network_binding(const NetworkBinding &binding) {
|
||||
std::lock_guard nlock{this->network.mutex};
|
||||
std::shared_ptr<ActiveNetworkBinding> abinding{};
|
||||
for(auto it = this->network.bindings.begin(); it != this->network.bindings.end(); it++) {
|
||||
abinding = *it;
|
||||
|
||||
if(net::address_equal(abinding->address, binding.address) && net::port(abinding->address) == net::port(binding.address)) {
|
||||
this->network.bindings.erase(it);
|
||||
break;
|
||||
}
|
||||
abinding = nullptr;
|
||||
}
|
||||
|
||||
if(binding->file_descriptor > 0)
|
||||
::close(binding->file_descriptor);
|
||||
binding->file_descriptor = 0;
|
||||
if(!abinding)
|
||||
return NetworkingUnbindResult::UNKNOWN_BINDING;
|
||||
|
||||
binding->handle = nullptr;
|
||||
if(abinding->accept_event) {
|
||||
event_del_block(abinding->accept_event);
|
||||
event_free(abinding->accept_event);
|
||||
abinding->accept_event = nullptr;
|
||||
}
|
||||
|
||||
if(abinding->file_descriptor > 0)
|
||||
::close(abinding->file_descriptor);
|
||||
abinding->file_descriptor = 0;
|
||||
abinding->handle = nullptr;
|
||||
|
||||
return NetworkingUnbindResult::SUCCESS;
|
||||
}
|
||||
|
||||
void LocalFileTransfer::shutdown_networking() {
|
||||
event_base* ev_base;
|
||||
std::thread dispatch_thread{};
|
||||
{
|
||||
std::lock_guard nlock{this->network.mutex};
|
||||
if(!this->network.active) return;
|
||||
this->network.active = false;
|
||||
|
||||
for(auto& binding : this->network.bindings) {
|
||||
if(binding->accept_event) {
|
||||
event_del_block(binding->accept_event);
|
||||
event_free(binding->accept_event);
|
||||
binding->accept_event = nullptr;
|
||||
}
|
||||
|
||||
if(binding->file_descriptor > 0)
|
||||
::close(binding->file_descriptor);
|
||||
binding->file_descriptor = 0;
|
||||
binding->handle = nullptr;
|
||||
}
|
||||
this->network.bindings.clear();
|
||||
|
||||
ev_base = std::exchange(this->network.event_base, nullptr);
|
||||
std::swap(this->network.dispatch_thread, dispatch_thread);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -269,12 +335,11 @@ void LocalFileTransfer::shutdown_networking() {
|
||||
}
|
||||
}
|
||||
|
||||
auto ev_base = std::exchange(this->network.event_base, nullptr);
|
||||
if(ev_base)
|
||||
event_base_loopbreak(ev_base);
|
||||
|
||||
if(this->network.dispatch_thread.joinable())
|
||||
this->network.dispatch_thread.join();
|
||||
if(dispatch_thread.joinable())
|
||||
dispatch_thread.join();
|
||||
|
||||
if(ev_base)
|
||||
event_base_free(ev_base);
|
||||
@@ -428,7 +493,7 @@ void LocalFileTransfer::finalize_client_ssl(const std::shared_ptr<FileClient> &c
|
||||
}
|
||||
|
||||
void LocalFileTransfer::callback_transfer_network_accept(int fd, short, void *ptr_binding) {
|
||||
auto binding = reinterpret_cast<NetworkBinding*>(ptr_binding);
|
||||
auto binding = reinterpret_cast<ActiveNetworkBinding*>(ptr_binding);
|
||||
auto transfer = binding->handle;
|
||||
|
||||
sockaddr_storage address{};
|
||||
|
||||
Reference in New Issue
Block a user