P2P NAT Punch-Through using STUN with Godot

357 views Asked by At

I'm trying to implement multiplayer in Godot using NAT Punch-Through. The idea is simple:

  • Player A clicks "Create Server" and is given an IP address and port (default 50000) from a STUN server
  • Player B enters the IP address and port into the "Join Server" bar and clicks connect
  • Player B is given their IP address and port from STUN, which they give back to Player A
  • Player A enters Player B's IP address, clicks "Connect To Player", and hole-punching is complete

Minimal Reproducible Example in Godot: https://github.com/BigBadE/GodotP2PHolePunch

In theory, with non-symmetrical NAT, that should work because Player A and Player B both send a packet to the correct public IP/port, so the router should allow the connection. However, it plays out like this (tested with two clients on the same machine):

Player A clicks "Create Server":

print("Started server on " + Singletons.public_ip + ":" + str(Singletons.public_port))
Singletons.peer.bind(Singletons.public_port)

(Where public_ip and public_port are gotten from the STUN server, and peer is a PacketPeerUDP)

Player B clicks "Join Server" with the IP address (twice, because when it freezes the print doesn't happen):

Singletons.peer.bind(Singletons.public_port)
// Actual code sets these to the correct peer public IP and port values
var ip = "localhost"
var port = 50000
Singletons.peer.connect_to_host(ip, port)
Singletons.peer.wait()
print("Got packet!")

Then Player A clicks "Connect to Player":

// Actual code sets these to the correct peer public IP and port values
ip = data[0]
port = int(data[1])

Singletons.peer.connect_to_host(ip, port)
Singletons.peer.put_packet("Test!".to_ascii_buffer())

The expected behavior is for Player B's client to unfreeze when the TCP packet is sent, but that never happens and the packet is never received. Why isn't the packet received with the correct public ip/port and peer public ip/port?

0

There are 0 answers