re annouce with exponential back-off
This commit is contained in:
		| @@ -67,6 +67,9 @@ add_library(solanaceae_sha1_ngcft1 | |||||||
| 	./solanaceae/ngc_ft1_sha1/participation.hpp | 	./solanaceae/ngc_ft1_sha1/participation.hpp | ||||||
| 	./solanaceae/ngc_ft1_sha1/participation.cpp | 	./solanaceae/ngc_ft1_sha1/participation.cpp | ||||||
|  |  | ||||||
|  | 	./solanaceae/ngc_ft1_sha1/re_announce_systems.hpp | ||||||
|  | 	./solanaceae/ngc_ft1_sha1/re_announce_systems.cpp | ||||||
|  |  | ||||||
| 	./solanaceae/ngc_ft1_sha1/chunk_picker_systems.hpp | 	./solanaceae/ngc_ft1_sha1/chunk_picker_systems.hpp | ||||||
| 	./solanaceae/ngc_ft1_sha1/chunk_picker_systems.cpp | 	./solanaceae/ngc_ft1_sha1/chunk_picker_systems.cpp | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,6 +25,25 @@ bool FT1ChunkSHA1Cache::haveChunk(const SHA1Digest& hash) const { | |||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void ReAnnounceTimer::set(const float new_timer) { | ||||||
|  | 	timer = new_timer; | ||||||
|  | 	last_max = new_timer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ReAnnounceTimer::reset(void) { | ||||||
|  | 	if (last_max <= 0.01f) { | ||||||
|  | 		last_max = 1.f; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	last_max *= 2.f; | ||||||
|  | 	timer = last_max; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ReAnnounceTimer::lower(void) { | ||||||
|  | 	timer *= 0.1f; | ||||||
|  | 	last_max *= 0.1f; | ||||||
|  | } | ||||||
|  |  | ||||||
| void TransferStatsTally::Peer::trimSent(const float time_now) { | void TransferStatsTally::Peer::trimSent(const float time_now) { | ||||||
| 	while (recently_sent.size() > 4 && time_now - recently_sent.front().time_point > 1.f) { | 	while (recently_sent.size() > 4 && time_now - recently_sent.front().time_point > 1.f) { | ||||||
| 		recently_sent.pop_front(); | 		recently_sent.pop_front(); | ||||||
|   | |||||||
| @@ -75,6 +75,23 @@ namespace Components { | |||||||
| 		float timer {0.f}; | 		float timer {0.f}; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  | 	struct AnnounceTargets { | ||||||
|  | 		entt::dense_set<Contact3> targets; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	struct ReAnnounceTimer { | ||||||
|  | 		float timer {0.f}; | ||||||
|  | 		float last_max {0.f}; | ||||||
|  |  | ||||||
|  | 		void set(const float new_timer); | ||||||
|  |  | ||||||
|  | 		// exponential back-off | ||||||
|  | 		void reset(void); | ||||||
|  |  | ||||||
|  | 		// on peer join to group | ||||||
|  | 		void lower(void); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
| 	struct DownloadPriority { | 	struct DownloadPriority { | ||||||
| 		// download/retreival priority in comparison to other objects | 		// download/retreival priority in comparison to other objects | ||||||
| 		// not all backends implement this | 		// not all backends implement this | ||||||
|   | |||||||
							
								
								
									
										83
									
								
								solanaceae/ngc_ft1_sha1/re_announce_systems.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								solanaceae/ngc_ft1_sha1/re_announce_systems.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | |||||||
|  | #include "./re_announce_systems.hpp" | ||||||
|  |  | ||||||
|  | #include "./components.hpp" | ||||||
|  | #include <solanaceae/message3/components.hpp> | ||||||
|  | #include <solanaceae/tox_contacts/components.hpp> | ||||||
|  | #include <solanaceae/ngc_ft1/ngcft1_file_kind.hpp> | ||||||
|  | #include <vector> | ||||||
|  | #include <cassert> | ||||||
|  |  | ||||||
|  | namespace Systems { | ||||||
|  |  | ||||||
|  | void re_announce( | ||||||
|  | 	ObjectRegistry& os_reg, | ||||||
|  | 	Contact3Registry& cr, | ||||||
|  | 	NGCEXTEventProvider& neep, | ||||||
|  | 	const float delta | ||||||
|  | ) { | ||||||
|  | 	std::vector<Object> to_remove; | ||||||
|  | 	os_reg.view<Components::ReAnnounceTimer>().each([&os_reg, &cr, &neep, &to_remove, delta](Object ov, Components::ReAnnounceTimer& rat) { | ||||||
|  | 		ObjectHandle o{os_reg, ov}; | ||||||
|  | 		// if paused -> remove | ||||||
|  | 		if (o.all_of<Message::Components::Transfer::TagPaused>()) { | ||||||
|  | 			to_remove.push_back(ov); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// if not downloading or info incomplete -> remove | ||||||
|  | 		if (!o.all_of<Components::FT1ChunkSHA1Cache, Components::FT1InfoSHA1Hash, Components::AnnounceTargets>()) { | ||||||
|  | 			to_remove.push_back(ov); | ||||||
|  | 			assert(false && "transfer in broken state"); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (o.get<Components::FT1ChunkSHA1Cache>().have_all) { | ||||||
|  | 			// transfer done, we stop announcing | ||||||
|  | 			to_remove.push_back(ov); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		// update all timers | ||||||
|  | 		rat.timer -= delta; | ||||||
|  |  | ||||||
|  | 		// send announces | ||||||
|  | 		if (rat.timer <= 0.f) { | ||||||
|  | 			rat.reset(); // exponential back-off | ||||||
|  |  | ||||||
|  | 			std::vector<uint8_t> announce_id; | ||||||
|  | 			const uint32_t file_kind = static_cast<uint32_t>(NGCFT1_file_kind::HASH_SHA1_INFO); | ||||||
|  | 			for (size_t i = 0; i < sizeof(file_kind); i++) { | ||||||
|  | 				announce_id.push_back((file_kind>>(i*8)) & 0xff); | ||||||
|  | 			} | ||||||
|  | 			assert(o.all_of<Components::FT1InfoSHA1Hash>()); | ||||||
|  | 			const auto& info_hash = o.get<Components::FT1InfoSHA1Hash>().hash; | ||||||
|  | 			announce_id.insert(announce_id.cend(), info_hash.cbegin(), info_hash.cend()); | ||||||
|  |  | ||||||
|  | 			for (const auto cv : o.get<Components::AnnounceTargets>().targets) { | ||||||
|  | 				if (cr.all_of<Contact::Components::ToxGroupPeerEphemeral>(cv)) { | ||||||
|  | 					// private ? | ||||||
|  | 					const auto [group_number, peer_number] = cr.get<Contact::Components::ToxGroupPeerEphemeral>(cv); | ||||||
|  | 					neep.send_pc1_announce(group_number, peer_number, announce_id.data(), announce_id.size()); | ||||||
|  | 				} else if (cr.all_of<Contact::Components::ToxGroupEphemeral>(cv)) { | ||||||
|  | 					// public | ||||||
|  | 					const auto group_number = cr.get<Contact::Components::ToxGroupEphemeral>(cv).group_number; | ||||||
|  | 					neep.send_all_pc1_announce(group_number, announce_id.data(), announce_id.size()); | ||||||
|  | 				} else { | ||||||
|  | 					assert(false && "we dont know how to announce to this target"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	for (const auto ov : to_remove) { | ||||||
|  | 		os_reg.remove<Components::ReAnnounceTimer>(ov); | ||||||
|  | 		// we keep the annouce target list around (if it exists) | ||||||
|  | 		// TODO: should we make the target list more generic? | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// TODO: how to handle unpause? | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // Systems | ||||||
|  |  | ||||||
							
								
								
									
										17
									
								
								solanaceae/ngc_ft1_sha1/re_announce_systems.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								solanaceae/ngc_ft1_sha1/re_announce_systems.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <solanaceae/object_store/object_store.hpp> | ||||||
|  | #include <solanaceae/contact/contact_model3.hpp> | ||||||
|  | #include <solanaceae/ngc_ext/ngcext.hpp> | ||||||
|  |  | ||||||
|  | namespace Systems { | ||||||
|  |  | ||||||
|  | void re_announce( | ||||||
|  | 	ObjectRegistry& os_reg, | ||||||
|  | 	Contact3Registry& cr, | ||||||
|  | 	NGCEXTEventProvider& neep, | ||||||
|  | 	const float delta | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | } // Systems | ||||||
|  |  | ||||||
| @@ -23,6 +23,7 @@ | |||||||
| #include "./chunk_picker.hpp" | #include "./chunk_picker.hpp" | ||||||
| #include "./participation.hpp" | #include "./participation.hpp" | ||||||
|  |  | ||||||
|  | #include "./re_announce_systems.hpp" | ||||||
| #include "./chunk_picker_systems.hpp" | #include "./chunk_picker_systems.hpp" | ||||||
| #include "./transfer_stats_systems.hpp" | #include "./transfer_stats_systems.hpp" | ||||||
|  |  | ||||||
| @@ -289,6 +290,8 @@ float SHA1_NGCFT1::iterate(float delta) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	Systems::re_announce(_os.registry(), _cr, _neep, delta); | ||||||
|  |  | ||||||
| 	{ // send out bitsets | 	{ // send out bitsets | ||||||
| 		// currently 1 per tick | 		// currently 1 per tick | ||||||
| 		if (!_queue_send_bitset.empty()) { | 		if (!_queue_send_bitset.empty()) { | ||||||
| @@ -531,33 +534,21 @@ bool SHA1_NGCFT1::onEvent(const Message::Events::MessageUpdated& e) { | |||||||
|  |  | ||||||
| 	ce.emplace<Message::Components::Transfer::File>(std::move(file_impl)); | 	ce.emplace<Message::Components::Transfer::File>(std::move(file_impl)); | ||||||
|  |  | ||||||
| 	// announce we are participating | 	// queue announce we are participating | ||||||
| 	// since this is the first time, we publicly announce to all | 	// since this is the first time, we publicly announce to all | ||||||
| 	if (e.e.all_of<Message::Components::ContactFrom, Message::Components::ContactTo>()) { | 	if (e.e.all_of<Message::Components::ContactFrom, Message::Components::ContactTo>()) { | ||||||
| 		const auto c_f = e.e.get<Message::Components::ContactFrom>().c; | 		const auto c_f = e.e.get<Message::Components::ContactFrom>().c; | ||||||
| 		const auto c_t = e.e.get<Message::Components::ContactTo>().c; | 		const auto c_t = e.e.get<Message::Components::ContactTo>().c; | ||||||
|  |  | ||||||
| 		std::vector<uint8_t> announce_id; |  | ||||||
| 		const uint32_t file_kind = static_cast<uint32_t>(NGCFT1_file_kind::HASH_SHA1_INFO); |  | ||||||
| 		for (size_t i = 0; i < sizeof(file_kind); i++) { |  | ||||||
| 			announce_id.push_back((file_kind>>(i*8)) & 0xff); |  | ||||||
| 		} |  | ||||||
| 		assert(ce.all_of<Components::FT1InfoSHA1Hash>()); |  | ||||||
| 		const auto& info_hash = ce.get<Components::FT1InfoSHA1Hash>().hash; |  | ||||||
| 		announce_id.insert(announce_id.cend(), info_hash.cbegin(), info_hash.cend()); |  | ||||||
|  |  | ||||||
| 		if (_cr.all_of<Contact::Components::ToxGroupEphemeral>(c_t)) { | 		if (_cr.all_of<Contact::Components::ToxGroupEphemeral>(c_t)) { | ||||||
| 			// public | 			// public | ||||||
| 			const auto group_number = _cr.get<Contact::Components::ToxGroupEphemeral>(c_t).group_number; | 			ce.get_or_emplace<Components::AnnounceTargets>().targets.emplace(c_t); | ||||||
|  |  | ||||||
| 			_neep.send_all_pc1_announce(group_number, announce_id.data(), announce_id.size()); |  | ||||||
| 		} else if (_cr.all_of<Contact::Components::ToxGroupPeerEphemeral>(c_f)) { | 		} else if (_cr.all_of<Contact::Components::ToxGroupPeerEphemeral>(c_f)) { | ||||||
| 			// private ? | 			// private ? | ||||||
| 			const auto [group_number, peer_number] = _cr.get<Contact::Components::ToxGroupPeerEphemeral>(c_f); | 			ce.get_or_emplace<Components::AnnounceTargets>().targets.emplace(c_f); | ||||||
|  |  | ||||||
| 			_neep.send_pc1_announce(group_number, peer_number, announce_id.data(), announce_id.size()); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	ce.get_or_emplace<Components::ReAnnounceTimer>(0.1f, 60.f*(_rng()%5120) / 1024.f).timer = (_rng()%512) / 1024.f; | ||||||
|  |  | ||||||
| 	ce.remove<Message::Components::Transfer::TagPaused>(); | 	ce.remove<Message::Components::Transfer::TagPaused>(); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user