python, webrtc and you

33
Python, WebRTC and You Saúl Ibarra Corretgé @saghul

Upload: saul-ibarra-corretge

Post on 15-Jul-2015

1.580 views

Category:

Technology


5 download

TRANSCRIPT

Page 1: Python, WebRTC and You

Python, WebRTC and YouSaúl Ibarra Corretgé

@saghul

Page 2: Python, WebRTC and You

print(“hello!”)

@saghul

FOSDEM

Open Source

Page 3: Python, WebRTC and You

github.com/saghul

Page 4: Python, WebRTC and You

Listen at your own risk

Page 5: Python, WebRTC and You

Do you know about WebRTC?

Page 6: Python, WebRTC and You

Have you ever used it?

Page 7: Python, WebRTC and You

What is WebRTC?

WebRTC (Web Real-Time Communication) is an API definition drafted by the World Wide Web Consortium (W3C) that supports browser-to-browser applications for voice calling, video chat, and P2P file sharing without the need of either internal or external plugins.

Page 8: Python, WebRTC and You
Page 9: Python, WebRTC and You
Page 10: Python, WebRTC and You

You need an adaptorImplementation in browsers is currently inconsistent

Some APIs are still in flux

I’ll be using rtcninja

https://github.com/eface2face/rtcninja.js

Page 11: Python, WebRTC and You

WebRTC APIs

getUserMedia

RTCPeerConnection

RTCDataChannel

Page 12: Python, WebRTC and You

getUserMediaif (!rtcninja.hasWebRTC()) { console.log('Are you from the past?!'); return;}!rtcninja.getUserMedia( // constraints {video: true, audio: true},! // successCallback function(localMediaStream) { var video = document.querySelector('video'); rtcninja.attachMediaStream(video, localMediaStream); },! // errorCallback function(err) { console.log("The following error occured: " + err); });

Page 13: Python, WebRTC and You
Page 14: Python, WebRTC and You

RTCPeerConnection

Handles streaming of media between 2 peers

Uses state of the art technology

ICE for NAT traversal

Page 15: Python, WebRTC and You

RTCPeerConnection (2)Get local media

Send SDP offer Get local media

Send SDP answer

Audio / Video

Page 16: Python, WebRTC and You
Page 17: Python, WebRTC and You
Page 18: Python, WebRTC and You

RTCDataChannelP2P, message boundary based channel for arbitrary data

Implemented using SCTP, different reliability choices possible

This is the game-changer

Did I mention it’s P2P?

Page 19: Python, WebRTC and You
Page 20: Python, WebRTC and You

What about the signalling?

It’s not specified!

Use SIP, XMPP, or your own!

Page 21: Python, WebRTC and You

Call Roulette

Page 22: Python, WebRTC and You

Saghul’s Imbecile Protocol

Page 23: Python, WebRTC and You

The ProtocolUsers enter the roulette when they connect over WebSocket

3 types of messages: offer_request, offer and answer

No end message, just disconnect the WebSocket

Page 24: Python, WebRTC and You
Page 25: Python, WebRTC and You

Shopping for a framework

Python >= 3.3, because future!

WebSocket support built-in

Async, because blocking is so 2001

New, because hype!

Page 26: Python, WebRTC and You

asyncio + aiohttp

Page 27: Python, WebRTC and You

@asyncio.coroutinedef init(loop): app = web.Application(loop=loop) app.router.add_route('GET', '/', LazyFileHandler(INDEX_FILE, 'text/html')) app.router.add_route('GET', '/ws', WebSocketHandler()) app.router.add_route('GET', '/static/{path:.*}', StaticFilesHandler(STATIC_FILES))! handler = app.make_handler() server = yield from loop.create_server(handler, '0.0.0.0', 8080) print("Server started at http://0.0.0.0:8080") return server, handler

Page 28: Python, WebRTC and You

class StaticFilesHandler: def __init__(self, base_path): self.base_path = base_path self.cache = {}! @asyncio.coroutine def __call__(self, request): path = request.match_info['path'] try: data, content_type = self.cache[path] except KeyError: full_path = os.path.join(self.base_path, path) try: with open(full_path, 'rb') as f: content_type, encoding = mimetypes.guess_type(full_path, strict=False) data = f.read() except IOError: log.warning('Could not open %s file' % path) raise web.HTTPNotFound() self.cache[path] = data, content_type log.debug('Loaded file %s (%s)' % (path, content_type)) return web.Response(body=data, content_type=content_type)

Page 29: Python, WebRTC and You

class WebSocketHandler: def __init__(self): self.waiter = None! @asyncio.coroutine def __call__(self, request): ws = web.WebSocketResponse(protocols=('callroulette',)) ws.start(request)! conn = Connection(ws) if self.waiter is None: self.waiter = asyncio.Future() fs = [conn.read(), self.waiter] done, pending = yield from asyncio.wait(fs, return_when=asyncio.FIRST_COMPLETED) if self.waiter not in done: # the connection was most likely closed self.waiter = None return ws other = self.waiter.result() self.waiter = None reading_task = pending.pop() asyncio.async(self.run_roulette(conn, other, reading_task)) else: self.waiter.set_result(conn)! yield from conn.wait_closed()! return ws

Page 30: Python, WebRTC and You

@asyncio.coroutine def run_roulette(self, peerA, peerB, initial_reading_task): log.info('Running roulette: %s, %s' % (peerA, peerB))! def _close_connections(): peerA.close() peerB.close()! # request offer data = dict(type='offer_request'); peerA.write(json.dumps(data))! # get offer # I cannot seem to cancel the reading task that was started before, which is the # only way one can know if the connection was closed, so use if for the initial # reading try: data = yield from asyncio.wait_for(initial_reading_task, READ_TIMEOUT) except asyncio.TimeoutError: data = '' if not data: return _close_connections()! data = json.loads(data) if data.get('type') != 'offer' or not data.get('sdp'): log.warning('Invalid offer received') return _close_connections()

Page 31: Python, WebRTC and You

# send offer data = dict(type='offer', sdp=data['sdp']); peerB.write(json.dumps(data))! # wait for answer data = yield from peerB.read(timeout=READ_TIMEOUT) if not data: return _close_connections()! data = json.loads(data) if data.get('type') != 'answer' or not data.get('sdp'): log.warning('Invalid answer received') return _close_connections()! # dispatch answer data = dict(type='answer', sdp=data['sdp']); peerA.write(json.dumps(data))! # wait for end fs = [peerA.read(), peerB.read()] yield from asyncio.wait(fs, return_when=asyncio.FIRST_COMPLETED)! # close connections return _close_connections()

Page 32: Python, WebRTC and You
Page 33: Python, WebRTC and You

Questions?

bettercallsaghul.com@saghul