feat(network): add selectable privacy-preserving discovery
This commit is contained in:
parent
9cf0c8fc9c
commit
4d31fd1517
26 changed files with 959 additions and 153 deletions
|
|
@ -178,16 +178,39 @@ func _run() -> void:
|
|||
)
|
||||
assert(not FileAccess.file_exists(discovery_settings_path))
|
||||
assert(discovery.set_room_name("Client Room"))
|
||||
assert(
|
||||
discovery.get_host_discovery_mode()
|
||||
== DiscoveryClient.HOST_DISCOVERY_PRIVATE
|
||||
)
|
||||
assert(discovery.set_host_connection_mode(
|
||||
DiscoveryClient.HOST_CONNECTION_RELAY
|
||||
))
|
||||
assert(
|
||||
discovery.get_host_connection_mode()
|
||||
== DiscoveryClient.HOST_CONNECTION_RELAY
|
||||
)
|
||||
assert(
|
||||
discovery.get_host_discovery_mode()
|
||||
== DiscoveryClient.HOST_DISCOVERY_PRIVATE
|
||||
)
|
||||
var client_settings: PackedByteArray = FileAccess.get_file_as_bytes(
|
||||
discovery_settings_path
|
||||
)
|
||||
assert(not client_settings.is_empty())
|
||||
var dedicated_discovery := DiscoveryClient.new()
|
||||
dedicated_discovery.call("_load_settings")
|
||||
dedicated_discovery.set(
|
||||
"_host_connection_preference",
|
||||
DiscoveryClient.HOST_CONNECTION_RELAY,
|
||||
)
|
||||
assert(
|
||||
dedicated_discovery.configure_dedicated_runtime("Headless Room")
|
||||
)
|
||||
assert(dedicated_discovery.get_room_name() == "Headless Room")
|
||||
assert(
|
||||
dedicated_discovery.get_host_connection_mode()
|
||||
== DiscoveryClient.HOST_CONNECTION_DIRECT
|
||||
)
|
||||
assert(
|
||||
FileAccess.get_file_as_bytes(discovery_settings_path)
|
||||
== client_settings
|
||||
|
|
@ -210,16 +233,26 @@ func _run() -> void:
|
|||
var listed_room := {
|
||||
"room_id": "empty-dedicated-room",
|
||||
"room_name": "Empty Dedicated Room",
|
||||
"address": "203.0.113.10",
|
||||
"port": 7777,
|
||||
"current_players": 0,
|
||||
"max_players": 8,
|
||||
"game_version": str(ProjectSettings.get_setting(
|
||||
"application/config/version", "unknown"
|
||||
)),
|
||||
"protocol_version": NetworkProtocol.PROTOCOL_VERSION,
|
||||
"connection_mode": "direct",
|
||||
"ip_privacy": "peer_visible",
|
||||
"host_kind": "dedicated",
|
||||
}
|
||||
assert(bool(discovery.call("_valid_public_room", listed_room)))
|
||||
assert(not listed_room.has("address"))
|
||||
assert(not listed_room.has("port"))
|
||||
var relayed_room: Dictionary = listed_room.duplicate(true)
|
||||
relayed_room["connection_mode"] = "relay"
|
||||
relayed_room["ip_privacy"] = "relayed"
|
||||
assert(not bool(discovery.call("_valid_public_room", relayed_room)))
|
||||
var player_relayed_room: Dictionary = relayed_room.duplicate(true)
|
||||
player_relayed_room["host_kind"] = "player"
|
||||
assert(bool(discovery.call("_valid_public_room", player_relayed_room)))
|
||||
var incompatible_room: Dictionary = listed_room.duplicate(true)
|
||||
incompatible_room["game_version"] = "0.0.0-alpha"
|
||||
assert(not bool(discovery.call("_valid_public_room", incompatible_room)))
|
||||
|
|
|
|||
98
tests/discovery_privacy_validation.gd
Normal file
98
tests/discovery_privacy_validation.gd
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
extends SceneTree
|
||||
|
||||
const FINGERPRINT: String = (
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"
|
||||
)
|
||||
const JoinGamePageScene: PackedScene = preload(
|
||||
"res://ui/network/join_game_page.tscn"
|
||||
)
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
var endpoint := EndpointParser.parse("203.0.113.20:49152")
|
||||
assert(endpoint.is_valid())
|
||||
var direct_route := ConnectionRoute.direct(endpoint)
|
||||
assert(direct_route.is_valid())
|
||||
assert("203.0.113.20" not in direct_route.display_description)
|
||||
var route := ConnectionRoute.discovery_direct(
|
||||
endpoint,
|
||||
"opaque-room-id",
|
||||
"Pond Friends",
|
||||
)
|
||||
assert(route.is_valid())
|
||||
assert(route.is_discovery_join())
|
||||
assert(route.display_description == "Pond Friends")
|
||||
assert("203.0.113.20" not in route.display_description)
|
||||
var relay_route := ConnectionRoute.discovery_relay(
|
||||
endpoint,
|
||||
"opaque-room-id",
|
||||
"Pond Friends",
|
||||
)
|
||||
assert(relay_route.is_valid())
|
||||
assert(relay_route.is_discovery_join())
|
||||
assert(relay_route.is_relay())
|
||||
assert("203.0.113.20" not in relay_route.display_description)
|
||||
|
||||
var join_page := JoinGamePageScene.instantiate() as JoinGamePage
|
||||
root.add_child(join_page)
|
||||
assert((join_page.get_node("%Address") as LineEdit).secret)
|
||||
assert(str(join_page.call("_display_endpoint", "203.0.113.20:49152")) == "*****")
|
||||
join_page.set("_addresses_visible", true)
|
||||
join_page.call("_refresh_address_privacy_controls")
|
||||
assert(not (join_page.get_node("%Address") as LineEdit).secret)
|
||||
assert(
|
||||
str(join_page.call("_display_endpoint", "203.0.113.20:49152"))
|
||||
== "203.0.113.20:49152"
|
||||
)
|
||||
var saved_entry := SavedServerEntry.new()
|
||||
saved_entry.kind = SavedServerEntry.Kind.SAVED
|
||||
saved_entry.display_name = "203.0.113.20"
|
||||
saved_entry.host = "203.0.113.20"
|
||||
saved_entry.normalized_host = "203.0.113.20"
|
||||
saved_entry.normalized_endpoint = "203.0.113.20:49152"
|
||||
join_page.set("_addresses_visible", false)
|
||||
assert(str(join_page.call("_display_entry_name", saved_entry)) == "saved server")
|
||||
join_page.set("_addresses_visible", true)
|
||||
assert(str(join_page.call("_display_entry_name", saved_entry)) == "203.0.113.20")
|
||||
|
||||
var data_root := PlayerDataRoot.new()
|
||||
root.add_child(data_root)
|
||||
var portable_path := ProjectSettings.globalize_path(
|
||||
"user://discovery-privacy-validation"
|
||||
)
|
||||
var created := data_root.create_unbound_root(portable_path)
|
||||
assert(bool(created.get("ok", false)))
|
||||
assert(data_root.activate_process_root(portable_path))
|
||||
|
||||
var store := ServerTrustStore.new()
|
||||
root.add_child(store)
|
||||
var trust_path := data_root.path_for(&"server_trust")
|
||||
store.configure_storage(trust_path, data_root)
|
||||
assert(store.verify_identity(FINGERPRINT) == ServerTrustStore.Verification.FIRST_SEEN)
|
||||
assert(store.trust_identity(FINGERPRINT, "Pond Friends"))
|
||||
assert(store.verify_identity(FINGERPRINT) == ServerTrustStore.Verification.MATCH)
|
||||
var saved_text := FileAccess.get_file_as_string(trust_path)
|
||||
assert("203.0.113.20" not in saved_text)
|
||||
assert("normalized_endpoint" not in saved_text)
|
||||
assert("normalized_host" not in saved_text)
|
||||
assert("\"port\"" not in saved_text)
|
||||
|
||||
var reloaded := ServerTrustStore.new()
|
||||
root.add_child(reloaded)
|
||||
reloaded.configure_storage(trust_path, data_root)
|
||||
assert(
|
||||
reloaded.verify_identity(FINGERPRINT)
|
||||
== ServerTrustStore.Verification.MATCH
|
||||
)
|
||||
var record := reloaded.get_identity_record(FINGERPRINT)
|
||||
assert(record.get("route_kind") == "discovery")
|
||||
assert(not record.has("normalized_endpoint"))
|
||||
assert(not record.has("normalized_host"))
|
||||
assert(not record.has("port"))
|
||||
|
||||
print("Discovery privacy validation: PASS")
|
||||
quit()
|
||||
1
tests/discovery_privacy_validation.gd.uid
Normal file
1
tests/discovery_privacy_validation.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://dmtlh1kpm7bl1
|
||||
Loading…
Add table
Add a link
Reference in a new issue