diff --git a/code/framework/src/networking/network_client.cpp b/code/framework/src/networking/network_client.cpp index c1fc21a82..903e9305e 100644 --- a/code/framework/src/networking/network_client.cpp +++ b/code/framework/src/networking/network_client.cpp @@ -339,6 +339,8 @@ namespace Framework::Networking { } void AssetFileTransfer::OnClosedConnection(const MafiaNet::SystemAddress &systemAddress, MafiaNet::RakNetGUID rakNetGUID, MafiaNet::PI2_LostConnectionReason lostConnectionReason) { + // Drops the sender's receivers; skipping it kept them alive until the peer shut down + MafiaNet::FileListTransfer::OnClosedConnection(systemAddress, rakNetGUID, lostConnectionReason); if (_cb) { _cb(); } diff --git a/code/tests/framework_ut.cpp b/code/tests/framework_ut.cpp index ac87303c5..f0983eb7c 100644 --- a/code/tests/framework_ut.cpp +++ b/code/tests/framework_ut.cpp @@ -11,6 +11,7 @@ #include "unit.h" /* TEST CATEGORIES */ +#include "modules/asset_transfer_ut.h" #include "modules/bitops_ut.h" #include "modules/connection_admission_ut.h" #include "modules/connection_gate_ut.h" @@ -78,6 +79,7 @@ int main() { UNIT_MODULE(result); UNIT_MODULE(network_packets); UNIT_MODULE(network_work); + UNIT_MODULE(asset_transfer); UNIT_MODULE(replication_authority); UNIT_MODULE(replication_rate); UNIT_MODULE(transform_batch); diff --git a/code/tests/modules/asset_transfer_ut.h b/code/tests/modules/asset_transfer_ut.h new file mode 100644 index 000000000..b784d3f5c --- /dev/null +++ b/code/tests/modules/asset_transfer_ut.h @@ -0,0 +1,62 @@ +/* + * MafiaHub OSS license + * Copyright (c) 2021-2026, MafiaHub. All rights reserved. + * + * This file comes from MafiaHub, hosted at https://github.com/MafiaHub/Framework. + * See LICENSE file in the source repository for information regarding licensing. + */ + +#pragma once + +#include "networking/network_client.h" + +#include + +namespace AssetTransferTest { + // Counts how often the transfer lets go of it. + class CountingHandler final: public MafiaNet::FileListTransferCBInterface { + public: + int dereferences = 0; + + bool OnFile(OnFileStruct *) override { + return true; + } + void OnFileProgress(FileProgressStruct *) override {} + void OnDereference() override { + ++dereferences; + } + }; +} // namespace AssetTransferTest + +// The client's asset transfer must still drop a sender's receivers when its connection closes, as the +// FileListTransfer it overrides does; otherwise they linger until the peer shuts down. +MODULE(asset_transfer, { + IT("drops the receivers of a sender whose connection closed", { + Framework::Networking::AssetFileTransfer transfer; + AssetTransferTest::CountingHandler handler; + MafiaNet::SystemAddress sender("127.0.0.1", 27015); + + const unsigned short setId = transfer.SetupReceive(&handler, false, sender); + EQUALS(transfer.IsHandlerActive(setId), true); + + transfer.OnClosedConnection(sender, MafiaNet::UNASSIGNED_RAKNET_GUID, MafiaNet::LCR_CONNECTION_LOST); + + EQUALS(transfer.IsHandlerActive(setId), false); + EQUALS(handler.dereferences, 1); + }); + + IT("keeps the receivers of other senders", { + Framework::Networking::AssetFileTransfer transfer; + AssetTransferTest::CountingHandler handler; + MafiaNet::SystemAddress sender("127.0.0.1", 27015); + MafiaNet::SystemAddress other("127.0.0.1", 27016); + + const unsigned short setId = transfer.SetupReceive(&handler, false, sender); + transfer.OnClosedConnection(other, MafiaNet::UNASSIGNED_RAKNET_GUID, MafiaNet::LCR_CONNECTION_LOST); + + EQUALS(transfer.IsHandlerActive(setId), true); + EQUALS(handler.dereferences, 0); + + transfer.CancelReceive(setId); + }); +});