|
| 1 | +[](https://gitpod.io/#https://github.com/ambianic/peerjs-python) |
| 2 | + |
| 3 | +# peerjs-python |
| 4 | + |
| 5 | +Python port of [PeerJS](https://github.com/peers) client. |
| 6 | + - Tracked in issue [#160](https://github.com/peers/peerjs/issues/610) of the official PeerJS project. |
| 7 | + |
| 8 | +Enables [Progressive Web Apps](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps) to discover and pair directly with Python apps using secure, browser supported [WebRTC](https://webrtc.org/) protocol. |
| 9 | + |
| 10 | +## Additional features: |
| 11 | + |
| 12 | +- *HTTP Proxy* over WebRTC data channel. It allows PeerJS browser clients to make remote REST requests over WebRTC to a local REST API running behind a firewall. |
| 13 | +- *Plug-and-play* functionality that allows seamless Airdrop-like pairing between peers running on the same local network. |
| 14 | + |
| 15 | +See Ambianic UI [PNP module](https://github.com/ambianic/ambianic-ui/blob/master/src/store/pnp.js) for a real-world example how PeerJS Python is used with PnP and HTTP Proxy. |
| 16 | + |
| 17 | +## Dependencies |
| 18 | + |
| 19 | +Uses [aiortc](https://github.com/aiortc/aiortc) as Python WebRTC provider. This requires installing a few native dependencies for audio/video media processing. |
| 20 | + |
| 21 | +On Debian/Ubuntu run: |
| 22 | +``` |
| 23 | +apt install libavdevice-dev libavfilter-dev libopus-dev libvpx-dev pkg-config libsrtp2-dev |
| 24 | +``` |
| 25 | +On OS X run: |
| 26 | +``` |
| 27 | +brew install ffmpeg opus libvpx pkg-config |
| 28 | +``` |
| 29 | + |
| 30 | +## Motivation |
| 31 | + |
| 32 | +This project was originally motivated while searching for a way to: |
| 33 | +- Connect a Progressive Web App ([Ambianic UI](https://github.com/ambianic/ambianic-ui)) directly and securely to an edge device ([Ambianic Edge](https://github.com/ambianic/ambianic-edge)) running Python app on a Raspberry Pi behind a home Internet router. |
| 34 | + |
| 35 | +[This article in WebRTCHacks](https://webrtchacks.com/private-home-surveillance-with-the-webrtc-datachannel/) provides more insight into the background of this project. |
| 36 | + |
| 37 | +## Main requirements |
| 38 | + |
| 39 | +- Easy Airdrop-like plug and play discovery and pairing between web app and edge devices. |
| 40 | +- Direct peer-to-peer connectivity to minimize: |
| 41 | + - latency |
| 42 | + - architecture complexity |
| 43 | + - costs associated with traffic and hosting of tunneling servers |
| 44 | + - exposure to public server security attacks |
| 45 | +- Support for: |
| 46 | + - Secure connections |
| 47 | + - Bi-directional data-channel |
| 48 | + - Low latency audio/video media streaming |
| 49 | + - Bi-directional live audio/video media |
| 50 | +- Rely only on [standard](https://www.w3.org/TR/webrtc/) broadly supported web browser features. |
| 51 | + - Stable mobile device support (iOS, Android, Raspberry Pi) |
| 52 | + - Stable desktop OS support (Windows, Mac OS, Linux) |
| 53 | + - No need for browser plug-ins |
| 54 | +- No intermediary cloud service providers to store and sync user data. |
| 55 | +- No tedious and complicated NAT setups of dynamic DNS with SSH tunnels between public IP servers and edge devices behind firewall. |
| 56 | +- High throughput and scalability via lightweight signaling service without a persistence layer. |
| 57 | + |
| 58 | +## Project Status |
| 59 | + |
| 60 | +Initial working prototype completed. PeerJS Python is now able to connect over WebRTC DataChannel to PeerJS in the browser and exchange messages. |
| 61 | + |
| 62 | +- [x] Complete and test connectivity with signaling server (peerjs-server). |
| 63 | +- [x] Complete and test data channel connectivity with web app peers. |
| 64 | +- [x] Release initial version to PyPi. |
| 65 | +- [x] support for python 3.7 & python 3.8 |
| 66 | +- [x] support for python 3.9 (see [dependency issue](https://github.com/ambianic/peerjs-python/issues/48)) |
| 67 | +- [ ] >90% code coverage with CI tests. |
| 68 | +- [ ] Port media support. |
| 69 | + |
| 70 | + |
| 71 | +## Code Examples |
| 72 | + |
| 73 | +A typical p2p session takes these steps: |
| 74 | +1. Establish signaling server session that enables peers to discover each other. |
| 75 | +2. Discover remote peer ID (either via signaling server room affinity or other means) |
| 76 | +3. Request connection to remote peer via signaling server |
| 77 | +4. Connect to remote peer via WebRTC ICE protocol. |
| 78 | +5. Exchange data or media with remote peer over p2p WebRTC connection. |
| 79 | + |
| 80 | +The following code snippet shows the initial part of establishing a signaling server connection. |
| 81 | + |
| 82 | +``` |
| 83 | + options = PeerOptions( |
| 84 | + host=config['host'], |
| 85 | + port=config['port'], |
| 86 | + secure=config['secure'], |
| 87 | + token=new_token, |
| 88 | + config=RTCConfiguration( |
| 89 | + iceServers=[RTCIceServer(**srv) for srv in config['ice_servers']] |
| 90 | + ) |
| 91 | + ) |
| 92 | + peer = Peer(id=savedPeerId, peer_options=options) |
| 93 | + await peer.start() |
| 94 | + log.info('peer activated') |
| 95 | + _setPnPServiceConnectionHandlers(peer) |
| 96 | +``` |
| 97 | + |
| 98 | +Once a signaling server connection is established, a peer can request connection to another peer or listen for requests from a remote peer. |
| 99 | +The example snippet bellow shows the latter: |
| 100 | + |
| 101 | +``` |
| 102 | + @peer.on(PeerEventType.Connection) |
| 103 | + async def peer_connection(peerConnection): |
| 104 | + log.info('Remote peer trying to establish connection') |
| 105 | + _setPeerConnectionHandlers(peerConnection) |
| 106 | +``` |
| 107 | + |
| 108 | +After a p2p connection is established, a peer can receive and send application messages. The following snippet shows how a peer receives a message: |
| 109 | + |
| 110 | +``` |
| 111 | + @peerConnection.on(ConnectionEventType.Data) |
| 112 | + async def pc_data(data): |
| 113 | + log.debug('data received from remote peer \n%r', data) |
| 114 | +``` |
| 115 | + |
| 116 | +For a complete working example see [this file](https://github.com/ambianic/peerjs-python/blob/master/src/peerjs/ext/http-proxy.py). |
| 117 | + |
| 118 | + |
| 119 | + |
| 120 | +## Other Related Open Source projects |
| 121 | + |
| 122 | +There are several great projects that solve the problem of accessing IoT devices behind firewall via tunneling servers. |
| 123 | + |
| 124 | +- [Python Proxy](https://github.com/qwj/python-proxy): Asynchronous tunnel proxy implemented in Python 3 asyncio. |
| 125 | +- [Proxy.py](https://github.com/abhinavsingh/proxy.py): HTTP proxy server written in Python. |
| 126 | +- [Inlets](https://github.com/inlets/inlets): Reverse proxy and service tunnel written in Go. |
| 127 | +- [Macchina.io](https://github.com/my-devices/sdk): IoT tunneling proxy written in C++. |
| 128 | + |
| 129 | +A few popular p2p projects that use WebRTC: |
| 130 | + |
| 131 | +- [Simple peer](https://github.com/feross/simple-peer) |
| 132 | +- [WebTorrent](https://webtorrent.io/) |
| 133 | +- [Ipfs](https://ipfs.io/) |
| 134 | +- [Matrix](https://matrix.org/) |
| 135 | + |
0 commit comments