TCP mesh almost working.

This commit is contained in:
Scott Duensing 2023-09-20 20:00:50 -05:00
parent 80d2cf654b
commit 738a9035ef
4 changed files with 125 additions and 88 deletions

View file

@ -56,8 +56,10 @@ func _data_recieved(type, data):
#***TODO**** We should really be displaying things in columns.
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"] + ") " + str(peer["ping"]) + "ms")
print(peer["online"])
if peer["online"]:
var child = peers_tree.create_item(root)
child.set_text(0, peer["user"] + " (" + peer["ip"] + ")")
# Handle empty peer list.
if data.size() == 0 and peers_tree.get_root() != null:
peers_tree.clear()

View file

@ -0,0 +1,24 @@
extends Node
func _process(_delta):
pass
func _ready():
Peers.peer_received_packet.connect(_received_packet)
func _received_packet(peer, verb, payload):
match verb:
"online":
if peer["online"] != payload["status"]:
peer["online"] = payload["status"]
peer["refresh"] = true
_:
print("UNKNOWN PACKET")
print(peer)
print(verb)
print(payload)
print()

View file

@ -1,17 +1,15 @@
extends Node
const ENET_SERVICE_EVENT_TYPE = 0
const ENET_SERVICE_PEER = 1
const ENET_SERVICE_EVENT_DATA = 2
const ENET_SERVICE_EVENT_CHANNEL = 3
signal peer_received_packet(peer, verb, payload)
var _basePort: int
var _tcp := TCPServer.new()
var _basePort : int
var _serverRunning: bool
var _timer : Timer
# This array is of dictionary elements that contain:
# "enet": ENet listening connnection.
# "id": Unique ID of this peer (1-254) based on IP.
# "ip": IP address of this peer.
# "port": Listen port of this peer.
@ -20,10 +18,10 @@ var _serverRunning: bool
var _userInfo: Dictionary
# This array is of dictionary elements that contain:
# "enet": ENet connection to this host.
# "tcp": TCP connection to this peer.
# "id": Unique ID of this peer (1-254) based on IP.
# "ip": IP address of this peer.
# "online": Will be true except when used to update the array.
# "online": Will be true when TCP network can talk to the peer.
# "port": Listen port of this peer.
# "user": User name on this IP.
# "uuid": UUID for this peer.
@ -44,50 +42,30 @@ var _userInfo: Dictionary
var peerArray: Array
func _on_timer_timeout():
if _serverRunning:
# Tell everyone we're alive.
for peer in peerArray:
if peer["tcp"] != null:
peer["tcp"].poll()
if peer["tcp"].get_status() == StreamPeerTCP.STATUS_CONNECTED:
send_to_peer(peer, "online", { "status": true })
func _process(_delta):
if _serverRunning:
# Handle current connections.
_process_enet(_userInfo["enet"], _userInfo["id"])
# Manage peer connections.
for peer in peerArray:
# Do we need new connections? It looks funny that we check for both connected and
# disconnected but there are other states the peer could be in.
if !is_peer_valid(peer):
print("Connecting to ", peer["ip"], ":", peer["port"])
peer["enet"] = _userInfo["enet"].connect_to_host(peer["ip"], peer["port"], 0)
else:
# Do we need to remove this one?
if is_peer_disconnected(peer):
peer["enet"] = null
func _process_enet(host: ENetConnection, id: int):
if host == null:
return
var ret = host.service() # Returns an array of ENET_SERVICE_* items.
match ret[ENET_SERVICE_EVENT_TYPE]:
host.EVENT_CONNECT:
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("Peer disconnected ", id, " (", host.get_peers().size(), " known peers)")
host.EVENT_ERROR:
print("Peer error ", id, " (", host.get_peers().size(), " known peers)")
#***TODO*** Attempt disconnect/reconnect
host.EVENT_NONE:
pass
host.EVENT_RECEIVE:
print("Peer recieved data ", id, " (", host.get_peers().size(), " known peers)")
_tcp_server()
func _ready():
_serverRunning = false
clear()
_timer = Timer.new()
_timer.wait_time = 1
_timer.one_shot = false
_timer.timeout.connect(_on_timer_timeout)
Engine.get_main_loop().current_scene.add_child(_timer)
_timer.start()
func _sort_by_ip(a, b):
@ -97,35 +75,70 @@ func _sort_by_ip(a, b):
return false
func _tcp_server():
if _tcp.is_listening():
# New inbound connection.
if _tcp.is_connection_available():
var new_peer: StreamPeerTCP = _tcp.take_connection()
# Do we have a connection for this peer already?
for peer in peerArray:
if peer["ip"] == new_peer.get_connected_host():
if peer["tcp"] == null:
# No - add it!
peer["tcp"] = new_peer
print("New peer ", peer["ip"], ":", peer["port"])
else:
# Yes. Close existing, use this one.
peer["tcp"].disconnect_from_host()
peer["tcp"] = new_peer
print("Updated peer ", peer["ip"], ":", peer["port"])
peer["tcp"].set_no_delay(true)
# Process incoming data and attempt connections.
for peer in peerArray:
if peer["tcp"] == null:
# Try to connect.
print("Connecting to ", peer["ip"], ":", peer["port"])
peer["tcp"] = StreamPeerTCP.new()
var error = peer["tcp"].connect_to_host(peer["ip"], peer["port"])
if error == OK:
peer["tcp"].set_no_delay(true)
else:
peer["tcp"] = null
else:
# Update network status.
peer["tcp"].poll()
# Still connected?
if peer["tcp"].get_status() == StreamPeerTCP.STATUS_ERROR:
peer["tcp"].disconnect_from_host()
peer["tcp"] = null
print("Lost peer ", peer["ip"], ":", peer["port"])
else:
# Data waiting?
if peer["tcp"].get_status() == StreamPeerTCP.STATUS_CONNECTED:
if peer["tcp"].get_available_bytes() > 0:
var data = peer["tcp"].get_var()
peer_received_packet.emit(peer, data["verb"], data["payload"])
func clear():
peerArray.clear()
func is_peer_connected(peer):
if is_peer_valid(peer):
if peer["enet"].get_state() == ENetPacketPeer.STATE_CONNECTED:
return true
return false
func is_peer_disconnected(peer):
if is_peer_valid(peer):
if peer["enet"].get_state() == ENetPacketPeer.STATE_DISCONNECTED:
return true
return false
func is_peer_valid(peer):
if typeof(peer["enet"]) == TYPE_OBJECT:
if peer["enet"] != null:
return true
return false
func is_running():
return _serverRunning
func send_to_peer(peer, verb: String, payload: Dictionary):
if peer["tcp"] != null:
if peer["tcp"].get_status() == StreamPeerTCP.STATUS_CONNECTED:
var message = {}
message["verb"] = verb
message["payload"] = payload
peer["tcp"].put_var(message)
peer["tcp"].poll()
func start_server(address, portStart, user, uuid):
if !_serverRunning:
clear()
@ -136,8 +149,7 @@ func start_server(address, portStart, user, 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)
_tcp.listen(_userInfo["port"], _userInfo["ip"])
_serverRunning = true
@ -145,8 +157,13 @@ func stop_server():
if _serverRunning:
# Tear down network.
_serverRunning = false
_userInfo["enet"].flush()
_userInfo["enet"].destroy()
for peer in peerArray:
if peer["tcp"] != null:
send_to_peer(peer, "online", { "status": false })
peer["tcp"].disconnect_from_host()
peer["tcp"] = null
print("Disconnected peer ", peer["ip"], ":", peer["port"])
_tcp.stop()
func update(peersFromCPP: Array):
@ -178,34 +195,27 @@ 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 is_peer_connected(peerCPP):
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["online"] = false
peerCPP["refresh"] = false
peerCPP["ping"] = 0.0
changed = true
# Also create the ENet connection data.
# Also create the TCP connection data.
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"] = null
# Sometimes the CPP code will return duplicates. Check.
# Also check if we need to redraw anyone.
found = false
for peer in peerArray:
if peer["ip"] == peerCPP["ip"]:
found = true
if peer["refresh"] == true:
peer["refresh"] = false
changed = true
peerCPP["tcp"] = null
# Add them to the new list.
peerArray.append(peerCPP)
# Check if we need to redraw anyone.
for peer in peerArray:
if peer["refresh"] == true:
peer["refresh"] = false
changed = true
# Sort new array.
peerArray.sort_custom(_sort_by_ip)

View file

@ -26,6 +26,7 @@ Process="*res://Scripts/process.gd"
Dialog="*res://Scripts/dialog.gd"
Edge="*res://Scripts/edge.gd"
Peers="*res://Scripts/peers.gd"
Network="*res://Scripts/network.gd"
Settings="*res://Scenes/settings.tscn"
About="*res://Scenes/about.tscn"
Manual="*res://Scenes/manual.tscn"