0
votes

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.

1
uh, what is your actual problem/question?Steffen Winkler
Hi sorry it's unclear. The problem I have is that we now have each other's ip address but we can't connect to each other p2p.Connor Huggett
You have to keep sending in intervals until you receive the other ends answer. One message is not enough.jgauffin
thanks so I should send to all ports above 1000 until it receives one? or should do 100~ either way of the port I received from the server?Connor Huggett
I've added uPnP to my application and it works completely now, but I still want to get the UDP hole punching working correctly because a lot of people will be nervous about enabling uPnP on their router, so I need hole punching to work where uPnP is disabled. However, uPnP will work if at least one of the people calling has it enabled.Connor Huggett

1 Answers

0
votes

You shouldn't have to scan all 65535 ports. You may find that some firewalls will block you if you do that. Your server should tell client1 the end point (public IP and port) of client2 and vise versa.

Feel free to use my example here: https://github.com/7wingfly/P2Pchat