I am trying to use UDP hole punching for a voip application. I currently have this part working:
- Open port not blocked by firewall on server (Port forwarding)
- Created UDP socket on client1
- Created UDP socket on client2
- Send packets over to Server application
- Server sends client1, client2's ip address and port and vice-versa
- clients successfully receive the other clients ip address and port
Now I'm having trouble with the final stage, this is the code I currently have. The problem I have is that whilst we have each others' ip addresses and ports we cannot connect to each other p2p. Does anyone have any suggestions?
- ContactIP = The contact's IP address returned from the server
ContactPort = the contactsPort returned from the server
private void PunchHole() { try { int range = 10000; if ((contactPort - range) < 1000) { contactPort = (contactPort + (range * 2)); } //else if ((contactPort + range) >= 65535) { range = range / 2; } int port = (contactPort - range); byte[] bytesToSend = Encoding.UTF8.GetBytes("Stop"); #region Punch hole through different ports - for loop //Console.WriteLine(port); for (int i = (contactPort - range); i < 65534; i++) { if (punchingHole) { udpClient.Send(bytesToSend, bytesToSend.Length, contactIP.ToString(), port); port++; } else { break; } } if (port >= 65533 && punchingHole) { range = range * 2; port = contactPort - range; if (port < 1000) { port = contactPort - (range / 2); } for (int i = port; i < 65534; i++) { if (punchingHole) { udpClient.Send(bytesToSend, bytesToSend.Length, contactIP.ToString(), port); port++; if (port >= 65533 && (contactPort + 1000) > range) { port = contactPort - range; i = port; continue; } } else { break; } } } if (punchingHole) { Console.WriteLine("Hole punch unsucessful."); } #endregion } catch (SocketException sockEx) { if (sockEx.SocketErrorCode == SocketError.Interrupted) { } else { MessageBox.Show(sockEx.Message, "PunchHole()"); } } catch (Exception ex) { MessageBox.Show(ex.Message, "PunchHole()");} } private void ListeningPort() { Console.WriteLine("Started Listening"); IPEndPoint listenEP = new IPEndPoint(IPAddress.Any, localPort); byte[] messageBytes = udpClient.Receive(ref listenEP); punchingHole = false; voiceCallEP = new IPEndPoint(listenEP.Address, listenEP.Port); message = Encoding.UTF8.GetString(messageBytes); Console.WriteLine(message); Console.WriteLine(listenEP.Address.ToString().PadRight(30) + listenEP.Port); udpClient.Send(messageBytes, messageBytes.Length, voiceCallEP); this.Invoke(new MethodInvoker(delegate() { label1.Text = "Hole punched succesfully."; })); InitialiseCall(); }
- localPort is the port which the client believe it is sending on (the private port of the machine)
EDIT: I've been tinkering around and got to this stage. It does work... but I'm obviously going through all the ports, this works but it's obviously a poor way to do it especially because it disconnects the Remote Desktop application I'm using to test the VOIP application on a computer in a different network.