From dfb92aef3c6a918907faa4fce4d083a2561b3cdc Mon Sep 17 00:00:00 2001 From: soksanichenko Date: Fri, 1 Jul 2022 12:32:19 +0300 Subject: [PATCH] Issues #562,#561,#560: - No source of entropy in _get_nearest_mirrors_by_network_data() - _get_nearest_mirrors_by_network_data() fails to exclude near-by private mirrors for extra options. - Exclude the private mirrors from the mirrors list in the case of fallback behavior --- src/backend/api/handlers.py | 40 +++++++++++++++++++++++++++++-------- src/backend/api/utils.py | 3 ++- src/backend/yaml_snippets | 2 +- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/backend/api/handlers.py b/src/backend/api/handlers.py index afd54d5f..40b30037 100644 --- a/src/backend/api/handlers.py +++ b/src/backend/api/handlers.py @@ -78,6 +78,21 @@ async def _get_nearest_mirrors_by_network_data( The function returns mirrors which are in the same subnet or have the same ASN as a request's IP """ + + def _is_additional_mirrors_suitable( + mirror_data: MirrorData, + main_list_of_mirrors: list[MirrorData] + ) -> bool: + """ + An additional mirror is a mirror + which is fresh (not outdated), not flapping and public, because + all suitable private mirrors we already found, + using ASN or subnets data + """ + return mirror_data.status == 'ok' and \ + not mirror_data.private and \ + mirror_data not in main_list_of_mirrors + match = get_geo_data_by_ip(ip_address) asn = get_asn_by_ip(ip_address) suitable_mirrors = [] @@ -105,14 +120,23 @@ async def _get_nearest_mirrors_by_network_data( if 1 <= len(suitable_mirrors) < LENGTH_CLOUD_MIRRORS_LIST\ and match is not None: continent, country, _, _, latitude, longitude = match + not_sorted_additional_mirrors = [ + mirror for mirror in mirrors if _is_additional_mirrors_suitable( + mirror_data=mirror, + main_list_of_mirrors=suitable_mirrors, + ) + ] + sorted_additional_mirrors = sort_mirrors_by_distance_and_country( + request_geo_data=(latitude, longitude), + mirrors=not_sorted_additional_mirrors, + country=country, + ) + randomized_additional_mirrors = randomize_mirrors_within_distance( + mirrors=sorted_additional_mirrors, + country=country, + )[:LENGTH_CLOUD_MIRRORS_LIST - len(suitable_mirrors)] suitable_mirrors.extend( - mirror['mirror'] for mirror in - sort_mirrors_by_distance_and_country( - request_geo_data=(latitude, longitude), - mirrors=[mirror for mirror in mirrors - if mirror not in suitable_mirrors], - country=country, - )[:LENGTH_CLOUD_MIRRORS_LIST - len(suitable_mirrors)] + mirror['mirror'] for mirror in randomized_additional_mirrors ) return suitable_mirrors @@ -186,7 +210,7 @@ async def _get_nearest_mirrors( if not suitable_mirrors: suitable_mirrors = await _get_nearest_mirrors_by_geo_data( ip_address=ip_address, - without_private_mirrors=without_private_mirrors, + without_private_mirrors=True, ) await set_mirrors_to_cache( ip_address, diff --git a/src/backend/api/utils.py b/src/backend/api/utils.py index ee6bf24e..0e87b7a8 100644 --- a/src/backend/api/utils.py +++ b/src/backend/api/utils.py @@ -152,7 +152,8 @@ def get_geo_data_by_ip( db = GeoIPEngine.get_instance() try: city = db.city(ip) - except AddressNotFoundError: + # ValueError will be raised in case of incorrect IP + except (AddressNotFoundError, ValueError): return try: city_name = city.city.name diff --git a/src/backend/yaml_snippets b/src/backend/yaml_snippets index 76213896..1dd0a625 160000 --- a/src/backend/yaml_snippets +++ b/src/backend/yaml_snippets @@ -1 +1 @@ -Subproject commit 76213896d0cae1911e1c869a524d86a916bdc804 +Subproject commit 1dd0a62524ff0404fba41e3efe1064c44081771d