this is only proof-of-concept for now, code and readme is just a temporary braindump and may change a lot - stay tuned :D
the goal is to provide a simple way to distribute and discover p2p-app-lobbies. a lobby is basically a "room" for people (peers) that are connected to each other via p2p (webrtc). in every lobby the connected peers run a specific application (javascript-program) that utilizes the connections between the peers in some way (video/audio, reliable and unreliable transport). apps can be created by loading the bundled source-code into the browser (drag&drop → indexedDB). there can be lobbies for all sorts of applications. like a video-chat or a p2p-game or file-sharing-app or a wiki or a package-manager-registry or ..
this excellent talk describes well what i want to have:
22C3 - Peer to peer under the hood (32:11).
using the terminiology of the talk, p2p-lobby would be an "application subnet"
and each lobby would be a "service subnet". so we have a p2p-network with
lots of peers that are not all connected to each other but only to N
randomly choosen peers. once peers join a lobby they make sure to be connected
to each other so the application can utilize the fully connected network
between all participating peers. at this point no server is needed for
the introduction of peers that join the lobby, it can be done through
the network the peers are already part of.
every user/peer can start/create a lobby that "hosts" an app and other users can join the lobby. the information about which lobbies are currently "hosting" which application and which peers are connected to it is distributed with throttled balanced slotted broadcasts. users who dont have the app's source-code will get it from the other peers - so there are no servers needed to host the applications.
p2p-lobby provides a user-interface to create apps and to create/join lobbies
but it can also be used programatically in any website/js-application.
or you can just download dist/p2plobby.html and browse
it via file:///..
.
anyway, this is just an idea for now and lots of things are unclear at the moment and need to be proof-of-concept'ed (i am currently writing an offline simulation with visualization to better understand how it would work). but basically the hard work has already been done by feross, mafintosh, substack and other amazing open-source-enthusiasts (see resources)! so if you have any suggestions or questions, please talk in #stackvm on freenode or create an issue!
p2p-lobby can be used in any website/js-app
var p2pl = require('p2p-lobby')()
either use the user-interface:
document.body.appendChild(p2pl.el)
or use the api programmatically:
// handle all the provided events
p2pl.on('error',onError)
p2pl.on('lobby',onLobby)
// connect to signaling servers
p2pl.connect(['https://example.com','https://signalhub.p2plobby.org','https://localhost:1337'])
// list lobbies
p2pl.lobbiesByHash['<hash-of-app-source>'] // array of lobbies hosting a specific app
p2pl.lobbies // array of lobbies
// join a lobby
var lobby = p2pl.lobbiesByHash['<hash-of-app-source>'][0]
// or: lobby = p2pl.lobbies[0]
lobby.join()
lobby.on('peer',onLobbyPeer) // not sure..
lobby.send('hello guys!')
lobby.leave()
// create a lobby
var lobby = p2pl.createLobby('<hash-of-app-source>')
lobby.on('peer',onLobbyPeer)
lobby.send('hello there! lets wait for 3 more and then start the game!')
lobby.leave()
// create an app
var app = p2pl.createApp(
{ name: 'name of the application'
, info: 'short information about this'
, logo: '<url-encoded-logo-picture>'
, source: App.toString()
} )
// a simple p2p-application
function App(lobby) {
console.log('the game will start immediately')
for (var i=0; i<lobby.peers.length; i++) addPeerToGame(lobby.peers[i])
tick()
function tick() {
logic()
render()
lobby.send(JSON.stringify({type:'control',data:'<user-input>'})
requestAnimationFrame(tick)
}
function addPeerToGame(p) {
p.on('data', function(d){
if (d.type == 'control') applyControl(p, d.data)
})
}
// ...
}
- users (peers) connect to a one or multiple (for redundancy and robustness) signalhub's (provided by the community or self-hosted) to introduce them to each other
- make it super easy (!) to host a server
- i would prefer to write the server in golang, so i can provide a
single binary one can just start
- i.e. port mafintosh/signalhub to golang
- a usecase would be where a group of people is on a lan without internet-connection. someone can just start a signaling-server in the lan and tell the others to connect to it for peer-introduction.
- i would prefer to write the server in golang, so i can provide a
single binary one can just start
- make it easy to introduce available servers to users
- users can store servers in indexedDB
- also provide a way to do server-less signaling (in the user-interface)
- users/peers store an asymmetric keypair in the browser via keyboot
- users can publish a signed message somewhere on the web (e.g. homepage, gist, anything with CORS enabled) to prove their identity
- what happens when the user loses the key-pair or is on another browser
and/or machine?
- make it possible to make backups
- make it possible to move/copy keypair to multiple browsers/devices
- make it possible to revoke keys?
- use multiple keypairs?
- currently keyboot only works properly in chrome (for me)
- the load event of the iframe is not fireing in firefox
- SharedWorker and thus page-bus is only supported by chrome and firefox
- this will hopefully get better and more robust over time (also ServiceWorker looks promising)
- also make it possible to use p2p-lobby without having to use keyboot (anonymous)
-
apps are stored locally in the browser via casboot. either the user uploads the app into the browser via drag&drop or gets the app via p2p from other users. an app consists of meta-data and the bundle which contains the source-code. we separate meta-data and bundle because otherwise the Merkle-DAG would contain too much data (i think..). so once a peer is connected it will receive
// <app-hash> points to the metadata in the Merkel Dag <app-hash> = sha1(JSON.stringify( { name : <app-name> // 1-200 characters ? , info : <app-info> // 1-400 characters ? , logo : <app-logo> // max 10kb base64(image) ? , source : <app-source-hash> // points to <app-source> in the content-addressable-store , author : <app-author> // fingerprint of public key , sign : <app-author-sign> // sign(<app-name><app-info><app-logo><app-source-hash><app-author>) } ))
- the json can be generated with
p2p-lobby
-cli or by drag&drop into the browser (then it will use the keyboot-keypair) <app-source>
(the content of the app-bundle) is not directly embedded into the<app-source-hash>
points to- maybe this could be distributed with webtorrent (instead of casboot)?
- make it possible to use p2p-lobby without having to use casboot
- throttled balanced slotted broadcasts
- put a
counter
on every message that gets increased everytime a peer forwards a message. peers only forward messages with acounter < N
.
- put a
- the json can be generated with
-
information about which lobbies are currently open/hosted is gossiped via hyperlog
-
a lobby consists of
- the lobby-id
- the app-hash of the app it is "hosting"
- the hash of public-keys of users that are in the lobby
-
the merkle dag would looks like this:
top-hash |-- <hash-0> lobby-for-appA | |-- <hash-0-0-0> lobby-for-appA-<lobbyId0> | | `-- <hash-0-0-1> lobby-for-appA-<lobbyId0> | | `-- <hash-0-0-2> lobby-for-appA-<lobbyId0> | |-- <hash-0-0> lobby-for-appA-<lobbyId1> | : |-- <hash-1> lobby-for-appB | :
-
-
how to join a lobby
- user-interface
- click
join
on a lobby in the list of lobbies
- click
- link
https://p2plobby.org#join-<lobbyId>
file:///Z:/path/to/p2plobby.html#join-<lobbyId>
- user-interface
-
how to create a lobby
- user-interface
- select an app in the list of available apps and click
create
- available apps are
- locally stored apps
- currently hosted apps (by other peers)
- select an app in the list of available apps and click
- link
- with app-hash
https://p2plobby.org#create-<app-hash>
file:///Z:/path/to/p2plobby.html#create-<app-hash>
- maybe also compressed source in the link? (see mrdoob/htmleditor)
https://p2plobby.org#createFromSource-<rawinflate(source-code)>
file:///Z:/path/to/p2plobby.html#createFromSource-<rawinflate(source-code)>
- this would automatically store the source-code in the content-addressable-store
- with app-hash
- user-interface
-
how is an app exactly defined? (see distribution)
-
should an app be signed by the keyboot-pair or some other keypair?
-
im currently separating app-metadata and app-bundle (the source-code) to avoid having to distribute too much data through the Merkel-DAG. so the peers can see name/info/logo of apps without having to download the app-bundle. im not sure about this. (see distribution)
-
how about putting the app-metadata right into the bundle?
-----BEGIN P2PLOBBY SIGNATURE----- { "name":"app name" , "info":"some info" , "logo":"<base64-encoded-image>" , "source-hash":"<hash-of-source-without-metadata>" , "author":"<author-fingerprint>" , "signature":"<sign>" } -----END P2PLOBBY SIGNATURE-----
-
-
when users join a lobby should the application take over immediately?
- how to get back to lobbies?
- put application in a sandboxed iframe so it cant change things outside?
- in chrome getUserMedia does not work in sandboxed iframe (chrome-issue 488991)
- load application in a new tab?
-
should apps be distributed via casboot or just some sort of api for webtorrent?
-
should p2plobby itself be hosted with hyperboot?
- i will host it with hyperboot anyway i think, but should it be advertised
to be loaded from
dist/p2p-lobby.html
? (because version/api/break?)
- i will host it with hyperboot anyway i think, but should it be advertised
to be loaded from
-
security
- what are attack-vectors?
- malicious apps
- the current approach (all the apps in one domain) make iframes useless
to protect anything since the iframe can just access
window.parent
(though i need to checkout CSP)- thats why i am currently doing
var app = new Function('lobby','<app-bundle>')
and then callapp(p2plobby.lobby)
- since every app inside p2p-lobby is hosted on the same domain,
a malicious app could access the camera-/audio-/desktop-stream?
- what is difference between visiting
https://malicious.com
and runninghttps://p2plobby.org#join-<malicious-app-lobby>
, assumed that a permission-schema is in place?
- what is difference between visiting
- http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
- https://w3c.github.io/webappsec/specs/content-security-policy/
- http://content-security-policy.com/
- thats why i am currently doing
- if we host every app on a subdomain (exactly like https://htmlb.in)
every app would require permissions explicitly
- proof (you have to grant permission explicitly per subdomain):
- what are the implications of hosting apps on subdomains?
- one has to host a p2p-lobby-server (beside signaling-servers),
you cant just drop the p2p-lobby.html somewhere (
file:///
, github, ..)- this server would not have to do much at all, just serve
/
on every subdomain. but still you have to deploy it
- this server would not have to do much at all, just serve
- one has to host a p2p-lobby-server (beside signaling-servers),
you cant just drop the p2p-lobby.html somewhere (
- because of the implications i want to make really sure that this would be the only way to be secure
- implement some permission-schema?
- the current approach (all the apps in one domain) make iframes useless
to protect anything since the iframe can just access
- ddos
- substack mentioned (00:35:40) something about ddos protection by throtteling based on round-robin
- malicious apps
- implement a "paranoid-mode" where you only connect to trusted peers
- what are attack-vectors?
- http://substack.net/offline_decentralized_single_sign_on_in_the_browser
- https://github.com/substack/omega-projects/issues/4
- https://github.com/substack/omega-projects/issues/8
- https://github.com/substack/jsconf-uy-2015
- https://github.com/substack/keyboot
- https://github.com/substack/hyperboot
- https://github.com/substack/peernet
- https://github.com/feross/simple-peer
- https://github.com/feross/webtorrent
- https://github.com/mafintosh/signalhub
- https://github.com/mafintosh/webrtc-swarm
- https://github.com/mafintosh/hyperlog
- https://github.com/moose-team/friends
- https://github.com/ssbc
- jbenet/random-ideas#20
- https://github.com/cjb/serverless-webrtc
- https://github.com/substack/rtcat
- http://www.ustream.tv/recorded/62296447 (anyone can edit)
- https://www.youtube.com/watch?v=hpaMPo-NyEQ