- client src/client
The peer to peer endpoint. Client can pull video-stream from peer to peer network with multi-channels. - source-client src/source-client
The live source client application. Based on QT5&SDL2. Pushing video-stream to edge-server. - edge-server src/edge-server
The main functions of it are pull stream from the source client, dispatch live stream to peers, etc. - tracker-server src/tracker-server
The main functions of it are peer to peer network control, UDP hole punching, etc. - libnet lib/net
libnet is a network library that uses IO multiplexing ( select/epoll ) and no-blocked IO, while using coroutines for each connection to improve IO response. Including coroutines, thread pool, timer, tcp/udp encapsulation, peer to peer network sending/receiving, tracker nodes exchanging, reliable udp make by KCP, hole punching. etc...
Setting up development environment with docker (optional):
# build image
docker build -t p2p-live .
# run docker container
docker run -i -t p2p-live /usr/bin/bash
cd root
git clone /url/to/repo
Building:
mkdir P2P-Live/build && cd P2P-Live/build
# set library path like -DCMAKE_PREFIX_PATH=/usr/local/lib
cmake ..
make -j
./build/bin/test-net
NAT types
- NAT1
Full Cone NAT- NAT2
Address-Restricted Cone NAT- NAT3
Port-Restricted Cone NAT- NAT4
Symmetric NAT
If PeerA wants to connect to PeerB:
Name | Address | Mark |
---|---|---|
ServerT | ipS:portS | RUDP listens connection request and detect NAT port |
PeerA | ipA:portA | PeerA local address |
PeerB | ipB:portB | PeerB local address |
NATA | ipNA:portNA | |
NATB | ipNB:portNB |
- PeerA sends a connection request to ServerT(ipS:portS) through RUDP.
- ServerT obtains NAT address (ipNA:portNA) of PeerA and forwards the request to PeerB through TCP long connection.
- PeerB attempts to connect to PeerA(ipNA:portNA) directly. If failed. PeerB sends a connection request to ServerT through RUDP.
- ServerT get PeerB's NAT address (ipNB:portNB) and transport the request to PeerA.
- PeerA attempts to connect to PeerB (ipNB:portNB).
- Once PeerA and PeerB send to each other, The hole punching is completed.
This method works only NATA and NATB is not Symmetric NAT.
But When NATA or NATB is Symmetric NAT?
Using port guessing may succeed but isn't stable. We don't process this condition.
If NTAA and NATB both symmetric NAT, We don't process it and just connect to edge server to get data.
It is a stackfull coroutine switch by Boost.Context. Coroutine uses:
- TCP When TCP acceptor accepts a new TCP client, a coroutine is built to process it. Coroutines are randomly assigned to the event loop for load balancing.
- UDP Not supports multi-coroutines, only one coroutine is used for sending and writing.
- RUDP Reliable UDP is built by KCP(ARQ) from UDP. A coroutine is built when tell RUDP to establish a new connection. Each connection has a send/recv queue and does not block each other.
How coroutines are scheduled? The scheduler has a dispatch queue and dispatches via FIFO. No need for cross-thread scheduling.
Put task to queue. Pop it up to run.
Ensure that the following packages are installed:
GPL-3.0 © Kadds