Slide 1

Slide 1 text

P2P JavaScript Adventures

Slide 2

Slide 2 text

24 years old

Slide 3

Slide 3 text

Hacker

Slide 4

Slide 4 text

say "hi"

Slide 5

Slide 5 text

filldisk.com

Slide 6

Slide 6 text

you can always make it work in the browser somehow

Slide 7

Slide 7 text

config.php~

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

dominic, substack, max, mafintosh

Slide 10

Slide 10 text

"Mad science"

Slide 11

Slide 11 text

WebRTC

Slide 12

Slide 12 text

PeerCDN Closed source, sold to Yahoo

Slide 13

Slide 13 text

WebTorrent

Slide 14

Slide 14 text

WebTorrent » Open source » Works in node & browser » No install (pure JavaScript) » Insanely fast » Exposes files as streams » Stream into , VLC, Chromecast, Airplay

Slide 15

Slide 15 text

var WebTorrent = require('webtorrent') var client = new WebTorrent() var magnetUri = '...' client.add(magnetUri, function (torrent) { console.log('Got torrent metadata!', torrent.infoHash) // Let's say the first file is a video var file = torrent.files[0] var video = document.createElement('video') document.body.appendChild(video) file.createReadStream().pipe(video) })

Slide 16

Slide 16 text

Is the browser fast enough for BitTorrent?

Slide 17

Slide 17 text

Browserify vs. Node » 888,614 ops/sec (browserify buffer.concat) » 1,832,307 ops/sec (node buffer.concat) » 4,094 ops/sec (browserify buffer.readDoubleBE) » 1,587,308 ops/sec (node buffer.readDoubleBE)

Slide 18

Slide 18 text

Buffer inherits from Object » Not meant for binary » slice() doesn't inherit from parent buffer » buffer[0] = 1000.22

Slide 19

Slide 19 text

Buffer should inherit from Uint8Array

Slide 20

Slide 20 text

function Buffer (length) { return new Uint8Array(length) }

Slide 21

Slide 21 text

function Buffer (length) { return augment(new Uint8Array(length)) } function augment (arr) { arr.write = Buffer.prototype.write arr.toString = Buffer.prototype.toString arr.toJSON = Buffer.prototype.toJSON arr.equals = Buffer.prototype.equals // … return arr }

Slide 22

Slide 22 text

Browserify vs. Node » 1,438,825 ops/sec ops/sec (browserify buffer.concat) » 1,832,307 ops/sec (node buffer.concat) » 1,057,233 ops/sec (browserify buffer.readDoubleBE) » 1,587,308 ops/sec (node buffer.readDoubleBE)

Slide 23

Slide 23 text

you can always make it work in the browser somehow

Slide 24

Slide 24 text

Extra credit » Passes iojs test suite » Use Object implementation for old browsers » Support IE6, 7, 8

Slide 25

Slide 25 text

Small modules

Slide 26

Slide 26 text

studynotes / package.json "dependencies": { "MD5": "^1.2.0", "add-commas": "0.0.4", "bcrypt": "^0.8.0", "body-parser": "^1.0.1", "compression": "^1.0.1", "connect-flash": "^0.1.1", "connect-mongo": "^0.7.0", "connect-slashes": "^1.2.0", "cookie-parser": "^1.0.1", "csurf": "^1.1.0", "debug": "^2.1.1", "escape-string-regexp": "^1.0.2", "express": "^4.0.0", "express-session": "^1.0.2", "font-awesome": "^4.2.0", "html-parser": "^0.8.0", "html-truncate": "^1.0.3", "http-status-codes": "^1.0.2", "humane-js": "^3.1.0", "jade": "^1.1.5", "jquery": "^2.1.1", "jsdom": "^4.0.2", "keymaster": "^1.6.2", "lodash.countby": "^3.0.0", "lodash.throttle": "^3.0.1", "maxcdn": "^0.1.5", "moment": "^2.5.1", "mongoose": "~3.8.0", "mongoose-validator": "^1.0.3", "nodemailer": "^1.1.1", "object-values": "^1.0.0", "once": "^1.3.0", "optimist": "^0.6.0", "passport": "^0.2.0", "passport-local": "^1.0.0", "posix": "^2.0.0", "run-auto": "^1.0.0", "run-parallel": "^1.0.0", "run-series": "^1.0.2", "run-waterfall": "^1.0.2", "serve-favicon": "^2.0.1", "simple-websocket": "^1.0.4", "stripe": "^3.1.0", "transparency": "^0.10.0", "underscore.string": "^3.0.1", "ws": "^0.7.0", "xtend": "^4.0.0" }

Slide 27

Slide 27 text

“When applications are done well, they are just the really application-specific, brackish residue that can't be so easily abstracted away. All the nice, reusable components sublimate away onto github and npm where everybody can collaborate to advance the commons.” — substack

Slide 28

Slide 28 text

webtorrent modules » bittorrent-dht (distributed hash table client) » bittorrent-tracker (tracker server/client) » bittorrent-protocol (bittorrent protocol stream) » create-torrent (create .torrent files) » parse-torrent (parse torrent identifiers) » simple-peer (simple WebRTC connections) » many more...

Slide 29

Slide 29 text

sharing P2P primitives

Slide 30

Slide 30 text

otrtalk » OTR (off-the-record messaging) » encryption » authentication » forward secrecy » uses DHT to discover buddies » telehash » bittorrent (bittorrent-dht)

Slide 31

Slide 31 text

mafintosh » peerflix (used by popcorn time) » torrent-mount » peerwiki

Slide 32

Slide 32 text

OPEN open source

Slide 33

Slide 33 text

easy to test

Slide 34

Slide 34 text

share your stackoverflow snippets

Slide 35

Slide 35 text

independently versioned

Slide 36

Slide 36 text

more likely to eventually be "done"

Slide 37

Slide 37 text

xhr var xhr = require('xhr') xhr('http://example.com', function (err, resp, body) { if (err) throw err console.log(body) })

Slide 38

Slide 38 text

drag-drop var dragDrop = require('drag-drop') dragDrop('#dropTarget', function (files) { console.log(files) // got the files })

Slide 39

Slide 39 text

WebRTC

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

simple-peer var SimplePeer = require('simple-peer') var peer1 = new SimplePeer({ initiator: true }) var peer2 = new SimplePeer() peer1.on('signal', function (data) { peer2.signal(data) }) peer2.on('signal', function (data) { peer1.signal(data) })

Slide 43

Slide 43 text

simple-peer peer1.send('hey peer2, how is it going?') peer2.on('data', function (data) { console.log('got a message from peer1: ' + data) })

Slide 44

Slide 44 text

browserify

Slide 45

Slide 45 text

the "browser" field in package.json

Slide 46

Slide 46 text

webtorrent / package.json { "browser": { "./lib/helper.js": "./lib/helper-browser.js" } }

Slide 47

Slide 47 text

webtorrent / package.json { "browser": { "bittorrent-tracker": "webtorrent-tracker" } }

Slide 48

Slide 48 text

jsdom / package.json { "browser": { "canvas": "false" } }

Slide 49

Slide 49 text

Streaming

Slide 50

Slide 50 text

http » uses HTTP range requests » supports video seeking

Slide 51

Slide 51 text

what about video from WebRTC? var data = new Buffer(1000000) // from remote peer var video = document.querySelector('video') var url = Object.createObjectURL(new Blob([ data ])) video.src = url video.play()

Slide 52

Slide 52 text

what about streaming? » Blob is immutable » we'll need a different approach

Slide 53

Slide 53 text

MediaSource API

Slide 54

Slide 54 text

MediaSource API » Allows JavaScript to generate media streams for playback » DASH ("Dynamic Adaptive Streaming over HTTP") » Change video quality as network conditions change » Supported in Chrome, IE11, Safari 8, Fx Nightly » Requires H.264 or VP8/9 codecs » Supports seeking

Slide 55

Slide 55 text

MediaSource API var mediaSource = new MediaSource() var video = document.querySelector('video') video.src = window.URL.createObjectURL(mediaSource) var sourceBuffer = mediaSource.addSourceBuffer('video/mp4') file.createReadStream().on('data', function (data) { sourceBuffer.appendBuffer(data) })

Slide 56

Slide 56 text

How does seeking work? » Requires video files conform to ISO MPEG-DASH » Basically NONE currently do » Requires your code to map timecode -> byte offset

Slide 57

Slide 57 text

seeking video.addEventListener('waiting', function () { var time = video.currentTime // stop fetching current byte range var byteOffset = timeToByte(time) // tell all peers to start giving me data from `byteOffset` file.createReadStream().on('data', function (data) { sourceBuffer.appendBuffer(data) }) })

Slide 58

Slide 58 text

time code -> byte offset » Usually MP4 files are conferted to ISO MPEG-DASH ("re-packaged") offline » For WebTorrent, what can we do?

Slide 59

Slide 59 text

can seeders repackage the video?

Slide 60

Slide 60 text

for new torrents, yes

Slide 61

Slide 61 text

for existing torrents?

Slide 62

Slide 62 text

no, hash verification would fail

Slide 63

Slide 63 text

can the downloader repackage the video?

Slide 64

Slide 64 text

yes, with mp4box.js! » process MP4 files in the browser » support for progressive parsing

Slide 65

Slide 65 text

var WebTorrent = require('webtorrent') var client = new WebTorrent() var magnetUri = '...' client.add(magnetUri, function (torrent) { var file = torrent.files[0] var video = document.createElement('video') document.body.appendChild(video) file.createReadStream().pipe(video) }) coming soon to webtorrent!

Slide 66

Slide 66 text

you can always make it work in the browser somehow

Slide 67

Slide 67 text

JavaScript Standard Style

Slide 68

Slide 68 text

What to do with good PRs that have poor code style?

Slide 69

Slide 69 text

give feedback, then wait

Slide 70

Slide 70 text

merge and fix it after

Slide 71

Slide 71 text

use a linter

Slide 72

Slide 72 text

super annoying .rc files » .jshintrc » .eslintrc » .jscsrc » how to keep them in sync?

Slide 73

Slide 73 text

standard $ npm install standard -g $ standard Error: Use JavaScript Standard Style lib/torrent.js:950:11: Expected '===' and instead saw '=='.

Slide 74

Slide 74 text

package.json { "name": "my-cool-package", "devDependencies": { "standard": "^3.0.0" }, "scripts": { "test": "standard && node tests.js" } }

Slide 75

Slide 75 text

saves time in two ways: » No configuration. The easiest way to enforce consistent style in your module/project. Just drop it in. » Catch style errors before they're submitted in PRs. Saves precious code review time by eliminating back-and-forth between maintainer and contributor.

Slide 76

Slide 76 text

“Adopting standard style means ranking the importance of community conventions higher than personal style, which does not make sense for 100% of projects and development cultures. At the same time, open source can be a hostile place for newbies. Setting up clear, automated contributor expectations makes a project healthier.” – Max Ogden

Slide 77

Slide 77 text

lots of people loved it » me » max ogden » mafintosh » henrik jorteg (&yet) » forrest norvell (npm) » lots more...

Slide 78

Slide 78 text

please add a config option for X!

Slide 79

Slide 79 text

lots of people had opinions "Like I said though, this is just my opinion..." "could we add X? maybe." "possibly" ";-)"

Slide 80

Slide 80 text

;

Slide 81

Slide 81 text

first rule of javascript: never talk about semicolons

Slide 82

Slide 82 text

objections to the name » not a TC39 or ECMA standard » "How dare you call this standard!"

Slide 83

Slide 83 text

semistandard » "All the goodness of feross/standard with semicolons sprinkled on top"

Slide 84

Slide 84 text

Slide 85

Slide 85 text

learn more about WebRTC » www.html5rocks.com/en/tutorials/webrtc/basics » webrtchacks.com » "simple-peer" on npm

Slide 86

Slide 86 text

learn more about webtorrent webtorrent.io webtorrent.io/roadmap