You do not need to join a project. You need to send or receive one JSON array. Pick the path that matches how you like to build.
Best if you write web pages, Python scripts, or anything that can speak UDP or WebSockets, and you do not want to deal with routing yourself.
-
Run a node. The Ruby version is the easiest to read:
git clone https://github.com/kermit4/cjp2p-ruby cd cjp2p-ruby ruby node.rbIt listens on UDP 24254 by default.
-
Talk to it. From a shell:
echo -n '[{"PleaseSendPeers":{}}]' | nc -u 127.0.0.1 24254You will get back a Peers message.
You are not depending on me. If my bootstrap nodes disappear, your local node still talks to anyone you know the IP of.
Best if you want zero dependencies and you are building a native app, game, or embedded device.
Implement three things and you are interoperable:
- Send and receive UDP packets containing UTF-8 JSON arrays of tagged values.
- Send the token (like a HTTP cookie) from
PleaseAlwaysReturnThisMessagewhenever messaging, usingAlwaysReturned, and send unique tokens for others to return to you. This is your anti-spoof. - Reply to
PleaseSendPeerswith a few IP:ports you know.
That is it. Example in Python:
import socket, json
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("0.0.0.0", 24254))
peers = set()
while True:
data, addr = s.recvfrom(65535)
try: msgs = json.loads(data.decode())
except: continue
out = []
for m in msgs:
if "PleaseSendPeers" in m:
out.append({"Peers":{"peers":list(peers)[:20]}})
if "ChatMessage" in m:
print(addr, m["ChatMessage"]["message"])
if out and "PleaseAlwaysReturnThisMessage" in m:
out.append({"AlwaysReturned": m["PleaseAlwaysReturnThisMessage"]})
peers.add(f"{addr[0]}:{addr[1]}")
if out: s.sendto(json.dumps(out).encode(), addr)Add ChatMessage, AudioFrame, or your own {"MyAppPing":{}} whenever you want. Old nodes ignore what they do not understand.
You now have NAT traversal for free, because you are sending from the same socket you listen on. No STUN server needed.
Best if you are a web developer who hates running native code.
Browsers cannot send raw UDP, but they can talk WebSocket to a tiny bridge you run locally. That bridge is 30 lines of Node or Go. It translates:
browser WebSocket JSON array <-> UDP packet to the internet
Publish the bridge code, not a service. Each user runs their own. No central relay, no account.
This is how https://azai.net/video.html works. The page does not connect to my server for media, it connects to your localhost bridge, which routes directly to the other peer.
- Want to prototype a chat in an hour? Path 1.
- Want to ship a game that does not rely on anyone? Path 2.
- Want to stay in the browser but keep p2p? Path 3.
All three speak the same arrays. A Ruby node, a Python script, and a web page can all be in the same swarm.
I wrote this so I can disappear. There is no registry, no version to update, no API key.
If you implement only PleaseReturnThisMessage, you can measure latency to others. If you implement only WhereAreThey and ChatMessage, you have a messenger. If you implement only PleaseSendContent, you have a file sharer.
You do not need my permission, my server, or my continued interest. Credit is appreciated, maintenance is not expected. Add your own messages, ignore mine if you like.
Start anywhere. The wire does not care.