Rolling my own ENet mesh network.

This commit is contained in:
Scott Duensing 2023-09-19 20:07:55 -05:00
parent ea991ab816
commit b72ddcbed1
7 changed files with 78 additions and 86 deletions

View file

@ -13,25 +13,25 @@ func _accepted():
_dialog.queue_free()
_result = true
emit_signal("_dialog_closed")
func _canceled():
_dialog.queue_free()
_result = false
emit_signal("_dialog_closed")
func _closed():
_dialog.queue_free()
emit_signal("_dialog_closed")
func _submitted(_text: String):
_dialog.queue_free()
_result = true
emit_signal("_dialog_closed")
func alert(title: String, text: String, parent: Node = null):
_dialog = AcceptDialog.new()
_dialog.dialog_text = text

View file

@ -75,8 +75,8 @@ func start_edge(community: String, key: String, supernode: String, port: int = 7
Engine.get_main_loop().current_scene.add_child(_timer)
_timer.timeout.emit()
return true
func stop_edge():
if _timer != null:
_timer.queue_free()

View file

@ -34,6 +34,12 @@ const HELP_ID_MANUAL = 1
var _ip := ""
func _clear_ui():
my_ip_label.text = ""
if peers_tree.get_root() != null:
peers_tree.clear()
func _data_recieved(type, data):
#print(type, ": ", data)
if type == "info":
@ -51,7 +57,7 @@ func _data_recieved(type, data):
var root = peers_tree.create_item()
for peer in Peers.peerArray:
var child = peers_tree.create_item(root)
child.set_text(0, peer["user"] + " (" + peer["ip"] + ")")
child.set_text(0, peer["user"] + " (" + peer["ip"] + ") " + str(peer["ping"]) + "ms")
# Handle empty peer list.
if data.size() == 0 and peers_tree.get_root() != null:
peers_tree.clear()
@ -61,22 +67,21 @@ func _go_offline():
if Peers.is_running():
Peers.stop_server()
Edge.stop_edge()
my_ip_label.text = ""
if peers_tree.get_root() != null:
peers_tree.clear()
_clear_ui()
func _network_died():
if Peers.is_running():
Peers.stop_server()
online_check_button.set_pressed_no_signal(false)
_clear_ui()
await Dialog.alert("Error", "The network layer unexpectedly stopped.")
func _notification(what):
if what == NOTIFICATION_WM_CLOSE_REQUEST:
_show_exit_dialog()
func _on_file_id_pressed(id):
match id:

View file

@ -7,7 +7,6 @@ const ENET_SERVICE_EVENT_DATA = 2
const ENET_SERVICE_EVENT_CHANNEL = 3
var _enet := ENetMultiplayerPeer.new()
var _basePort: int
var _serverRunning: bool
@ -45,20 +44,9 @@ var _userInfo: Dictionary
var peerArray: Array
func _peer_connected(id):
print("Peer %d connected" % id)
func _peer_disconnected(id):
print("Peer %d disconnected" % id)
func _process(_delta):
if _serverRunning:
#_process_enet(_userInfo["enet"], _userInfo["id"])
for peer in peerArray:
_process_enet(peer["enet"], peer["id"])
_enet.poll()
_process_enet(_userInfo["enet"], _userInfo["id"])
func _process_enet(host: ENetConnection, id: int):
@ -67,87 +55,84 @@ func _process_enet(host: ENetConnection, id: int):
var ret = host.service() # Returns an array of ENET_SERVICE_* items.
match ret[ENET_SERVICE_EVENT_TYPE]:
host.EVENT_CONNECT:
print("Adding host %d" % id)
_enet.add_mesh_peer(id, host)
print("Peer connected ", id, " (", host.get_peers().size(), " known peers)")
#var enet_peers = host.get_peers()
#for enet_peer in enet_peers:
host.EVENT_DISCONNECT:
print("Mesh peer disconnected %d" % id)
host = null
print("Peer disconnected ", id, " (", host.get_peers().size(), " known peers)")
host.EVENT_ERROR:
print("Mesh peer error %d" % id)
host = null
print("Peer error ", id, " (", host.get_peers().size(), " known peers)")
#***TODO*** Attempt disconnect/reconnect
host.EVENT_NONE:
pass
host.EVENT_RECEIVE:
print("Mesh peer recieved data %d" % id)
print("Peer recieved data ", id, " (", host.get_peers().size(), " known peers)")
func _ready():
_serverRunning = false
clear()
multiplayer.peer_connected.connect(_peer_connected)
multiplayer.peer_disconnected.connect(_peer_disconnected)
func _sort_by_ip(a, b):
# Sort numerically.
if Util.ip_string_to_int(a["ip"]) < Util.ip_string_to_int(b["ip"]):
return true
return false
func clear():
peerArray.clear()
func is_running():
return _serverRunning
func start_server(address, portStart, user, uuid):
clear()
_basePort = portStart
_userInfo["ip"] = address
_userInfo["user"] = user
_userInfo["uuid"] = uuid
_userInfo["id"] = _userInfo["ip"].get_slice(".", 3).to_int() # Use last octet for our ID.
_userInfo["port"] = _basePort + _userInfo["id"]
# Create mesh network.
_enet.create_mesh(_userInfo["id"])
multiplayer.set_multiplayer_peer(_enet)
# Set up our listening port.
_userInfo["enet"] = ENetConnection.new()
_userInfo["enet"].create_host_bound(_userInfo["ip"], _userInfo["port"], 256, 0)
_serverRunning = true
if !_serverRunning:
clear()
_basePort = portStart
_userInfo["ip"] = address
_userInfo["user"] = user
_userInfo["uuid"] = uuid
_userInfo["id"] = _userInfo["ip"].get_slice(".", 3).to_int() # Use last octet for our ID.
_userInfo["port"] = _basePort + _userInfo["id"]
# Set up our listening port.
_userInfo["enet"] = ENetConnection.new()
_userInfo["enet"].create_host_bound(_userInfo["ip"], _userInfo["port"], 256, 0)
_serverRunning = true
func stop_server():
# Tear down network.
_serverRunning = false
multiplayer.set_multiplayer_peer(null)
if _serverRunning:
# Tear down network.
_serverRunning = false
_userInfo["enet"].flush()
_userInfo["enet"].destroy()
func update(peersFromCPP: Array):
var found
var changed = false
var oldArray: Array = []
if !_serverRunning:
return
#print("\nPeers Raw: ", peersFromCPP)
#print("Peers Before: ", peerArray)
# Remember what we started with.
oldArray = peerArray.duplicate(true)
# Start a new peer list.
peerArray.clear()
# Add everyone connected.
for peerCPP in peersFromCPP:
# Get an IP without netmask.
@ -158,19 +143,22 @@ func update(peersFromCPP: Array):
if oldPeer["ip"] == peerCPP["ip"]:
found = true
peerCPP = oldPeer
# Update peer statistics. ***TODO*** These do not set 'changed' and are not refreshed.
if typeof(peerCPP["enet"]) == TYPE_OBJECT:
if peerCPP["enet"].get_state() == ENetPacketPeer.STATE_CONNECTED:
peerCPP["ping"] = peerCPP["enet"].get_statistic(ENetPacketPeer.PEER_ROUND_TRIP_TIME)
if !found:
# We didn't have them. Add needed records.
peerCPP["user"] = ""
peerCPP["uuid"] = ""
peerCPP["online"] = true
peerCPP["refresh"] = false
peerCPP["ping"] = 0.0
changed = true
# Also create the ENet connection to them.
peerCPP["id"] = peerCPP["ip"].get_slice(".", 3).to_int() # Use last octet for our ID.
peerCPP["port"] = _basePort + peerCPP["ip"].get_slice(".", 3).to_int()
peerCPP["enet"] = ENetConnection.new()
peerCPP["enet"].create_host(1)
peerCPP["enet"].connect_to_host(peerCPP["ip"], peerCPP["port"], 0)
peerCPP["enet"] = _userInfo["enet"].connect_to_host(peerCPP["ip"], peerCPP["port"], 0)
print("Connecting to ", peerCPP["ip"], ":", peerCPP["port"])
# Sometimes the CPP code will return duplicates. Check.
# Also check if we need to redraw anyone.
@ -181,7 +169,7 @@ func update(peersFromCPP: Array):
if peer["refresh"] == true:
peer["refresh"] = false
changed = true
# Add them to the new list.
peerArray.append(peerCPP)
@ -189,5 +177,5 @@ func update(peersFromCPP: Array):
peerArray.sort_custom(_sort_by_ip)
#print("Peers After: ", peerArray)
return changed
return changed

View file

@ -28,7 +28,7 @@ func _elevate_unix(program: String, arguments: PackedStringArray):
func _elevate_windows(program: String, arguments: PackedStringArray):
pass
func _process(_delta):
if _udp.is_listening():
@ -49,15 +49,14 @@ func elevate(program: String, arguments: PackedStringArray):
return await _elevate_windows(program, arguments)
else:
return await _elevate_unix(program, arguments)
func shutdown():
_udp.stop()
if FileAccess.file_exists(_ask_pass_script):
print("Removing ", _ask_pass_script)
DirAccess.remove_absolute(_ask_pass_script)
func startup(port: int = 19999):
_ask_pass_port = port
_udp.listen(_ask_pass_port, "127.0.0.1")

View file

@ -55,8 +55,8 @@ func load_settings():
compression_check_button.button_pressed = config.get_value("settings", "compression", true)
auto_start_check_button.button_pressed = config.get_value("settings", "autoStart", false)
uuid = config.get_value("settings", "identity", Uuid.v4())
func save_settings():
# Validate IP address, if needed.
if !ip_check_button.button_pressed:
@ -90,7 +90,7 @@ func save_settings():
#config.set_value("settings", "position", DisplayServer.window_get_position())
config.set_value("settings", "identity", uuid)
config.save("user://network.cfg")
func _on_ip_check_button_toggled(_toggled_on):
ip_line_edit.editable = !ip_check_button.button_pressed

View file

@ -36,7 +36,7 @@ func _deep_equal_one_way(a, b):
return a == b
return true
func deep_equal(a, b):
return _deep_equal_one_way(a, b) && _deep_equal_one_way(b, a)
@ -52,7 +52,7 @@ func generate_password(length: int = 16):
for i in range(length):
password += alpha_num[randi() % len(alpha_num)]
return password
func ip_string_to_int(ip: String):
var result = 0