P2P-Live icon indicating copy to clipboard operation
P2P-Live copied to clipboard

A P2P-based online live broadcast system

A P2P-based online live broadcast system

GPL-3.0 status
Build:master Test:master Lint:master

Projects

  • 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...

Building

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

Testing

./build/bin/test-net

Detailed Design

UDP hole punching

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
  1. PeerA sends a connection request to ServerT(ipS:portS) through RUDP.
  2. ServerT obtains NAT address (ipNA:portNA) of PeerA and forwards the request to PeerB through TCP long connection.
  3. PeerB attempts to connect to PeerA(ipNA:portNA) directly. If failed. PeerB sends a connection request to ServerT through RUDP.
  4. ServerT get PeerB's NAT address (ipNB:portNB) and transport the request to PeerA.
  5. PeerA attempts to connect to PeerB (ipNB:portNB).
  6. 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.

Coroutines

It is a stackfull coroutine switch by Boost.Context. Coroutine uses:

  1. 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.
  2. UDP Not supports multi-coroutines, only one coroutine is used for sending and writing.
  3. 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.

Thread pool

Put task to queue. Pop it up to run.

Third-party

Ensure that the following packages are installed:

Maintainers

@Kadds.
@YShaw99.

License

GPL-3.0 © Kadds