I wrote a program that sets-up peer-to-peer links. The programm, which can be found at http://basyl.co.uk/code/punch/doc/files/Readme-txt.html, is in two parts: a server that runs on a public host; and a client that is used by each end of the desired peer-to-peer link.
I have access to two public servers: 'bonn' (home.contextshift.co.uk) and 'entropy' (home2.contextshift.co.uk)
If the server is on bonn and clients are run on bonn, entropy and my home PC (behind NAT), a punched connection from entropy can talk to my PC without problem. However, a connection from bonn to the PC fails; data from the PC reaches bonn, but data from bonn back through the NAT hole never arrives.
If the server is on entropy and again, clients are run on bonn, entropy and my PC, punched connections work fine between all clients.
This is confusing as the server is not involved in the peer-to-peer data flow. If you are still with me, here is the flow:
- Client-A connects to Server on a TCP link and gets a unique token;
Client-B connects to Server on a TCP link and gets a unique token;
Client-A and Client-B receive updates over their TCP link telling them who else is attached;
Client-A (or B) sends a request to the Server over a newly created UDP link passing its token and the name of Client-B;
The Server identifies Client-A from the token and forwards the request to Client-B over its TCP link, including A's UDP address/port number in the request;
Client-A (or B) sends a confirmation to the Server over a newly created UDP link, passing its token and the name of Client-A;
The Server identifies Client-B from the token and forwards the request to Client-A over its TCP link, including B's UDP address/port number in the request;
A and B now have the UDP address/port of the other and can ping each other and exchange data.
As you can see, the Server never talks on the UDP links created by the Clients for their requests, only on the TCP links.
So in summary, the client doesn't work on a particular host when the server is on the same host. Any suggestions for reasons for this behaviour or for ways I could investigate this further?
Note that this test is artificial because the point of the hole punching is to talk between two hosts both behind NAT. This in fact works, wherever the server is, so the problem might be considered academic.
Note also that before writing the program, I tried using a public app called 'NatCheck'. This also failed in a similar way, although I didn't investigate it much - it required three public hosts and I modified it to use just my two. When it failed to work, I assumed that I had screwed up in some way and discarded the app.
Any comments on the code also highly welcome (I will probably post it on the code review site).