Programming P2P application

P2P connectivity in a nutshell. Assume we’re talking about UDP here. The steps below can also be applied to TCP with some adjustments.

  1. Enumerate all your local IP addresses (usually only 1). Create a UDP socket on a given port number** for each adapter with an IP address.

  2. For each socket created in step 1, contact a STUN or TURN server with that same socket to discover your external IP address and to discover what the internal port number maps to outside of the NAT (it’s not always the same port value). That is, your local address 192.168.1.2:4900 might be 128.11.12.13:8888 to the outside world. And some NATs don’t always use the same port mapping when using the same local port to other IP addresses. TURN will also provide you a “relay address”. You can also use UPNP to get a port mapped address directly from your router, if it supports that protocol.

  3. Through a rendezvous service (SIP, XMPP, instant message, web service, email, cups with strings), publish your address candidate list to a service or send a notification to the other client that says, “hey, I want to connect with you”. This message includes all the “address candidates” (ip and port pairs) collected in steps 1 and 2.

  4. The remote client, upon receiving the invite to connect, performs step 1 and 2 above as well. Then sends back his candidate list through the same channel that he received the inviter’s candidate list on.

  5. Hole punching step. Both clients, start sending test messages over UDP to the other side’s address candidates and listening for the same messages on their end. Whenever a messages is received, reply back to the address from which it came. Eventually, the clients will discover that they have a pair of addresses that they can reliably send datagrams too. Typically, one endpoint makes the final decision on which address pair (sockets) to communicate with and the protocol facilitates this endpoint telling the other endpoint this decision.

**- usually best to not to rely on a well known port for P2P clients. Because two clients behind the same NAT or firewall would not likely be able to use your software at the same time.

Here is a quick summary of some technologies to explore.

STUN – Is a simple server and protocol for clients behind a NAT/route to discover what their external IP and port mappings are.

TURN is an expansion to STUN, but supports relaying for P2P connectivity scenarios where firewalls and NATs prevent direct connections.

ICE is a set of steps by which STUN and TURN are used for setting up a P2P connection. ICE is a formal protocol for steps 1-5 above. Two excellent set of slides on ICE are here and here.

WebRTC is a variant of the ICE standard as well as a reference library for make P2P sessions with STUN and TURN.

UPNP + Internet Gateway Device Protocol – Some routers support this for hosts to automatically obtain port mappings.

libnice is an open source C library for Linux (and might work on windows) that implements ICE.

libjingle is another ICE implementation (in C++) from Google. For Windows and Linux.

PJNATH is a library within the PJSIP suite of coding libraries. It is a good implementation of an ICE stack (C code) and has been ported to a lot of platforms. (Windows, Linux, Mac, iOS, Symbian, and soon Android).

And finally, I have a blatant plug for you to use my STUN server code base.

Leave a Comment