SlideShare ist ein Scribd-Unternehmen logo
1 von 49
Downloaden Sie, um offline zu lesen
Python, WebRTC and You
Saúl Ibarra Corretgé

@saghul
v2
github.com/saghul
WebRTC, anyone?
Have you ever used it?
Internals, anyone?
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.
Well,
everyone
better
Restart
Their
Chrome
You need an adapter
Implementation in browsers is
currently inconsistent

Some APIs are still in flux
rtcninja.js
https://github.com/eface2face/rtcninja.js

Nice name, right?!
Temasys WebRTC
Plugin
Free (as in beer) plugin for IE and
Safari

http://skylink.io/plugin/
WebRTC APIs
getUserMedia

RTCPeerConnection

RTCDataChannel
getUserMedia
if (!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);	
}	
);
RTCPeerConnection
Handles streaming of media between
2 peers

Uses state of the art technology

JSEP
RTCPeerConnection (2)
Get local media Send SDP offer
Get local media
Send SDP answer
ICE candidates
Audio / Video
Interactive Connectivity Establishment
ICE
Helps find the best path for media

Solves NAT traversal and other
hostile network problems

Communication Consent Verification

It can trickle!
What about the
signalling?
It’s not specified!

Use SIP, XMPP or roll your own!
RTCDataChannel
P2P, message boundary based
channel for arbitrary data

Implemented using SCTP, different
reliability choices possible
Call Roulette
Python
JavaScript
The Protocol
WebSocket based, JSON payload

Users enter the roulette when they
connect over WebSocket

Session is negotiated / established

No end message, just disconnect the
WebSocket
Saghul’s Imbecile Protocol
(v1)
yo
(v2)
{'yo': 'yo'}
{'jsep': {'sdp': '...',	
'type': 'offer'},	
'yo': 'yo'}
{'jsep': {'sdp': '...',	
'type': 'answer'},	
'yo': 'yo'}
{'candidate': {'candidate': '...',	
'sdpMLineIndex': 1,	
'sdpMid': ''},	
'yo': 'yo'}
Shopping for a
framework
Python >= 3.3, because future!

WebSocket support built-in

Async, because blocking is so 2001

New, because why not?
asyncio + aiohttp
github.com/saghul/CallRoulette
@asyncio.coroutine	
def 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
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)
class WebSocketHandler:	
def __init__(self):	
self.waiter = None	
!
@asyncio.coroutine	
def __call__(self, request):	
ws = web.WebSocketResponse(protocols=('callroulette-v2',))	
ws.start(request)	
!
conn = Connection(ws)	
if self.waiter is None:	
self.waiter = asyncio.Future(loop=ws._loop)	
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()

reading_task.cancel()	
asyncio.async(self.run_roulette(conn, other))	
else:	
self.waiter.set_result(conn)	
!
yield from conn.wait_closed()	
!
return ws
from jsonmodels import models, fields	
from jsonmodels.errors import ValidationError	
!
!
class StringChoiceField(fields.StringField):	
def __init__(self, choices=None, *args, **kw):	
self.choices = choices or []	
super(StringChoiceField, self).__init__(*args, **kw)	
!
def validate(self, value):	
if value not in self.choices:	
raise ValidationError('invalid choice value')	
super(StringChoiceField, self).validate(value)	
!
class Jsep(models.Base):	
type = StringChoiceField(choices=['offer', 'answer'], required=True)	
sdp = fields.StringField(required=True)	
!
class Candidate(models.Base):	
candidate = fields.StringField(required=True)	
sdpMid = fields.StringField(required=True)	
sdpMLineIndex = fields.IntField(required=True)	
!
class YoPayload(models.Base):	
yo = fields.StringField(required=True)	
jsep = fields.EmbeddedField(Jsep)	
candidate = fields.EmbeddedField(Candidate)
@asyncio.coroutine	
def run_roulette(self, peerA, peerB):	
log.info('Running roulette: %s, %s' % (peerA, peerB))	
!
@asyncio.coroutine	
def close_connections():	
yield from asyncio.wait([peerA.close(), peerB.close()],

return_when=asyncio.ALL_COMPLETED)	
!
def parse(data):	
try:	
data = json.loads(data)	
payload = YoPayload(**data)	
payload.validate()	
except Exception as e:	
log.warning('Error parsing payload: %s' % e)	
return None	
return payload
# request offer	
offer_request = YoPayload(yo='yo')	
peerA.write(json.dumps(offer_request.to_struct()))	
!
# get offer	
data = yield from peerA.read(timeout=READ_TIMEOUT)	
if not data:	
yield from close_connections()	
return	
!
offer = parse(data)	
if offer is None or offer.jsep is None or offer.jsep.type != 'offer':	
log.warning('Invalid offer received')	
yield from close_connections()	
return	
!
# send offer	
peerB.write(json.dumps(offer.to_struct()))
# wait for answer	
data = yield from peerB.read(timeout=READ_TIMEOUT)	
if not data:	
yield from close_connections()	
return	
!
answer = parse(data)	
if answer is None or answer.jsep is None or answer.jsep.type != 'answer':	
log.warning('Invalid answer received')	
yield from close_connections()	
return	
!
# dispatch answer	
peerA.write(json.dumps(answer.to_struct()))
# wait for candidates / end	
while True:	
peer_a_read = asyncio.async(peerA.read())	
peer_a_read.other_peer = peerB	
peer_b_read = asyncio.async(peerB.read())	
peer_b_read.other_peer = peerA	
done, pending = yield from asyncio.wait([peer_a_read, peer_b_read],	
return_when=asyncio.FIRST_COMPLETED)	
for task in pending:	
task.cancel()	
for task in done:	
data = task.result()	
if not data:	
break	
# all we can get at this point is trickled ICE candidates	
candidate = parse(data)	
if candidate is None or candidate.candidate is None:	
log.warning('Invalid candidate received!')	
break	
task.other_peer.write(json.dumps(candidate.to_struct()))	
else:	
continue	
break	
# close connections	
yield from close_connections()
In WebRTC trouble?
bettercallsaghul.com
@saghul

Weitere ähnliche Inhalte

Was ist angesagt?

Firefox OS Introduction at Bontouch
Firefox OS Introduction at BontouchFirefox OS Introduction at Bontouch
Firefox OS Introduction at Bontouch
Robert Nyman
 
Composer
ComposerComposer
Composer
cmodijk
 

Was ist angesagt? (20)

Perl Dancer for Python programmers
Perl Dancer for Python programmersPerl Dancer for Python programmers
Perl Dancer for Python programmers
 
Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...
Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...
Strangers In The Night: Ruby, Rack y Sinatra - Herramientas potentes para con...
 
Sprockets
SprocketsSprockets
Sprockets
 
Firefox OS Introduction at Bontouch
Firefox OS Introduction at BontouchFirefox OS Introduction at Bontouch
Firefox OS Introduction at Bontouch
 
Pyramid Lighter/Faster/Better web apps
Pyramid Lighter/Faster/Better web appsPyramid Lighter/Faster/Better web apps
Pyramid Lighter/Faster/Better web apps
 
CouchDB Google
CouchDB GoogleCouchDB Google
CouchDB Google
 
Puppet Camp Phoenix 2015: Managing Files via Puppet: Let Me Count The Ways (B...
Puppet Camp Phoenix 2015: Managing Files via Puppet: Let Me Count The Ways (B...Puppet Camp Phoenix 2015: Managing Files via Puppet: Let Me Count The Ways (B...
Puppet Camp Phoenix 2015: Managing Files via Puppet: Let Me Count The Ways (B...
 
HTML5 Real-Time and Connectivity
HTML5 Real-Time and ConnectivityHTML5 Real-Time and Connectivity
HTML5 Real-Time and Connectivity
 
Real time server
Real time serverReal time server
Real time server
 
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
 
WordCamp Montreal 2016 WP-API + React with server rendering
WordCamp Montreal 2016  WP-API + React with server renderingWordCamp Montreal 2016  WP-API + React with server rendering
WordCamp Montreal 2016 WP-API + React with server rendering
 
WordPress mit Composer und Git verwalten
WordPress mit Composer und Git verwaltenWordPress mit Composer und Git verwalten
WordPress mit Composer und Git verwalten
 
The goodies of zope, pyramid, and plone (2)
The goodies of zope, pyramid, and plone (2)The goodies of zope, pyramid, and plone (2)
The goodies of zope, pyramid, and plone (2)
 
Composer
ComposerComposer
Composer
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
 
Mashing up JavaScript
Mashing up JavaScriptMashing up JavaScript
Mashing up JavaScript
 
Python RESTful webservices with Python: Flask and Django solutions
Python RESTful webservices with Python: Flask and Django solutionsPython RESTful webservices with Python: Flask and Django solutions
Python RESTful webservices with Python: Flask and Django solutions
 
Flask - Backend com Python - Semcomp 18
Flask - Backend com Python - Semcomp 18Flask - Backend com Python - Semcomp 18
Flask - Backend com Python - Semcomp 18
 
Cors michael
Cors michaelCors michael
Cors michael
 
PHP BASIC PRESENTATION
PHP BASIC PRESENTATIONPHP BASIC PRESENTATION
PHP BASIC PRESENTATION
 

Andere mochten auch

Andere mochten auch (20)

Python, WebRTC and You
Python, WebRTC and YouPython, WebRTC and You
Python, WebRTC and You
 
Planning libuv v2
Planning libuv v2Planning libuv v2
Planning libuv v2
 
CDRTool: CDR mediation and rating engine for OpenSIPS
CDRTool: CDR mediation and rating engine for OpenSIPSCDRTool: CDR mediation and rating engine for OpenSIPS
CDRTool: CDR mediation and rating engine for OpenSIPS
 
Trust No One
Trust No OneTrust No One
Trust No One
 
The Future of the PBX
The Future of the PBXThe Future of the PBX
The Future of the PBX
 
WebRTC enabling your OpenSIPS infrastructure
WebRTC enabling your OpenSIPS infrastructureWebRTC enabling your OpenSIPS infrastructure
WebRTC enabling your OpenSIPS infrastructure
 
libuv, NodeJS and everything in between
libuv, NodeJS and everything in betweenlibuv, NodeJS and everything in between
libuv, NodeJS and everything in between
 
Building an Open Source VoIP Hardware Phone
Building an Open Source VoIP Hardware PhoneBuilding an Open Source VoIP Hardware Phone
Building an Open Source VoIP Hardware Phone
 
From SIP to WebRTC and vice versa
From SIP to WebRTC and vice versaFrom SIP to WebRTC and vice versa
From SIP to WebRTC and vice versa
 
Proyecto Open Pi Phone
Proyecto Open Pi PhoneProyecto Open Pi Phone
Proyecto Open Pi Phone
 
SylkServer: State of the art RTC application server
SylkServer: State of the art RTC application serverSylkServer: State of the art RTC application server
SylkServer: State of the art RTC application server
 
Escalabilidad horizontal desde las trincheras
Escalabilidad horizontal desde las trincherasEscalabilidad horizontal desde las trincheras
Escalabilidad horizontal desde las trincheras
 
A deep dive into libuv
A deep dive into libuvA deep dive into libuv
A deep dive into libuv
 
libuv: cross platform asynchronous i/o
libuv: cross platform asynchronous i/olibuv: cross platform asynchronous i/o
libuv: cross platform asynchronous i/o
 
Videoconferencias: el santo grial de WebRTC
Videoconferencias: el santo grial de WebRTCVideoconferencias: el santo grial de WebRTC
Videoconferencias: el santo grial de WebRTC
 
Jitsi: State of the Union
Jitsi: State of the UnionJitsi: State of the Union
Jitsi: State of the Union
 
Asyncio
AsyncioAsyncio
Asyncio
 
Introduction to asyncio
Introduction to asyncioIntroduction to asyncio
Introduction to asyncio
 
Rethinking the PBX
Rethinking the PBXRethinking the PBX
Rethinking the PBX
 
Developing rich SIP applications with SIPSIMPLE SDK
Developing rich SIP applications with SIPSIMPLE SDKDeveloping rich SIP applications with SIPSIMPLE SDK
Developing rich SIP applications with SIPSIMPLE SDK
 

Ähnlich wie Python, WebRTC and You (v2)

Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)
Remy Sharp
 
Is html5-ready-workshop-110727181512-phpapp02
Is html5-ready-workshop-110727181512-phpapp02Is html5-ready-workshop-110727181512-phpapp02
Is html5-ready-workshop-110727181512-phpapp02
PL dream
 

Ähnlich wie Python, WebRTC and You (v2) (20)

soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.js
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar Django
 
Browsers with Wings
Browsers with WingsBrowsers with Wings
Browsers with Wings
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMR
 
SwampDragon presentation: The Copenhagen Django Meetup Group
SwampDragon presentation: The Copenhagen Django Meetup GroupSwampDragon presentation: The Copenhagen Django Meetup Group
SwampDragon presentation: The Copenhagen Django Meetup Group
 
A More Flash Like Web?
A More Flash Like Web?A More Flash Like Web?
A More Flash Like Web?
 
Nodejs and WebSockets
Nodejs and WebSocketsNodejs and WebSockets
Nodejs and WebSockets
 
Protocol-Oriented Programming in Swift
Protocol-Oriented Programming in SwiftProtocol-Oriented Programming in Swift
Protocol-Oriented Programming in Swift
 
An Introduction To jQuery
An Introduction To jQueryAn Introduction To jQuery
An Introduction To jQuery
 
Event-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 EngineEvent-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 Engine
 
HTML5 - Daha Flash bir web?
HTML5 - Daha Flash bir web?HTML5 - Daha Flash bir web?
HTML5 - Daha Flash bir web?
 
NodeJS
NodeJSNodeJS
NodeJS
 
Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)
 
Is html5-ready-workshop-110727181512-phpapp02
Is html5-ready-workshop-110727181512-phpapp02Is html5-ready-workshop-110727181512-phpapp02
Is html5-ready-workshop-110727181512-phpapp02
 
Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)Node.js vs Play Framework (with Japanese subtitles)
Node.js vs Play Framework (with Japanese subtitles)
 
Cross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App EngineCross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App Engine
 
Intro to JavaFX & Widget FX
Intro to JavaFX & Widget FXIntro to JavaFX & Widget FX
Intro to JavaFX & Widget FX
 
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディングXitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
 
Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014
 
huhu
huhuhuhu
huhu
 

Mehr von Saúl Ibarra Corretgé

Mehr von Saúl Ibarra Corretgé (15)

Challenges running Jitsi Meet at scale during the pandemic
Challenges running Jitsi Meet at scale during the pandemicChallenges running Jitsi Meet at scale during the pandemic
Challenges running Jitsi Meet at scale during the pandemic
 
The Road to End-to-End Encryption in Jitsi Meet
The Road to End-to-End Encryption in Jitsi MeetThe Road to End-to-End Encryption in Jitsi Meet
The Road to End-to-End Encryption in Jitsi Meet
 
Jitsi: State of the Union 2020
Jitsi: State of the Union 2020Jitsi: State of the Union 2020
Jitsi: State of the Union 2020
 
Jitsi Meet: our tale of blood, sweat, tears and love
Jitsi Meet: our tale of blood, sweat, tears and loveJitsi Meet: our tale of blood, sweat, tears and love
Jitsi Meet: our tale of blood, sweat, tears and love
 
Jitsi Meet: Video conferencing for the privacy minded
Jitsi Meet: Video conferencing for the privacy mindedJitsi Meet: Video conferencing for the privacy minded
Jitsi Meet: Video conferencing for the privacy minded
 
Jitsi - Estado de la unión 2019
Jitsi - Estado de la unión 2019Jitsi - Estado de la unión 2019
Jitsi - Estado de la unión 2019
 
Get a room! Spot: the ultimate physical meeting room experience
Get a room! Spot: the ultimate physical meeting room experienceGet a room! Spot: the ultimate physical meeting room experience
Get a room! Spot: the ultimate physical meeting room experience
 
Going Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTCGoing Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTC
 
Going Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTCGoing Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTC
 
Jitsi: Estado de la Unión (2018)
Jitsi: Estado de la Unión (2018)Jitsi: Estado de la Unión (2018)
Jitsi: Estado de la Unión (2018)
 
Jitsi: state-of-the-art video conferencing you can self-host
Jitsi: state-of-the-art video conferencing you can self-hostJitsi: state-of-the-art video conferencing you can self-host
Jitsi: state-of-the-art video conferencing you can self-host
 
WebRTC: El epicentro de la videoconferencia y IoT
WebRTC: El epicentro de la videoconferencia y IoTWebRTC: El epicentro de la videoconferencia y IoT
WebRTC: El epicentro de la videoconferencia y IoT
 
Jitsi: Open Source Video Conferencing
Jitsi: Open Source Video ConferencingJitsi: Open Source Video Conferencing
Jitsi: Open Source Video Conferencing
 
Extendiendo SIP con WebRTC
Extendiendo SIP con WebRTCExtendiendo SIP con WebRTC
Extendiendo SIP con WebRTC
 
De SIP a WebRTC y vice versa
De SIP a WebRTC y vice versaDe SIP a WebRTC y vice versa
De SIP a WebRTC y vice versa
 

Kürzlich hochgeladen

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Kürzlich hochgeladen (20)

08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 

Python, WebRTC and You (v2)

  • 1. Python, WebRTC and You Saúl Ibarra Corretgé
 @saghul v2
  • 4. Have you ever used it?
  • 6. 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.
  • 7.
  • 8.
  • 9.
  • 11. You need an adapter Implementation in browsers is currently inconsistent Some APIs are still in flux
  • 13. Temasys WebRTC Plugin Free (as in beer) plugin for IE and Safari http://skylink.io/plugin/
  • 15. getUserMedia if (!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); } );
  • 16.
  • 17. RTCPeerConnection Handles streaming of media between 2 peers Uses state of the art technology JSEP
  • 18. RTCPeerConnection (2) Get local media Send SDP offer Get local media Send SDP answer ICE candidates Audio / Video
  • 20. ICE Helps find the best path for media Solves NAT traversal and other hostile network problems Communication Consent Verification It can trickle!
  • 21.
  • 22. What about the signalling? It’s not specified! Use SIP, XMPP or roll your own!
  • 23.
  • 24.
  • 25. RTCDataChannel P2P, message boundary based channel for arbitrary data Implemented using SCTP, different reliability choices possible
  • 26.
  • 29. The Protocol WebSocket based, JSON payload Users enter the roulette when they connect over WebSocket Session is negotiated / established No end message, just disconnect the WebSocket
  • 33. {'jsep': {'sdp': '...', 'type': 'offer'}, 'yo': 'yo'}
  • 34. {'jsep': {'sdp': '...', 'type': 'answer'}, 'yo': 'yo'}
  • 36.
  • 37. Shopping for a framework Python >= 3.3, because future! WebSocket support built-in Async, because blocking is so 2001 New, because why not?
  • 40. @asyncio.coroutine def 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
  • 41. 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)
  • 42. class WebSocketHandler: def __init__(self): self.waiter = None ! @asyncio.coroutine def __call__(self, request): ws = web.WebSocketResponse(protocols=('callroulette-v2',)) ws.start(request) ! conn = Connection(ws) if self.waiter is None: self.waiter = asyncio.Future(loop=ws._loop) 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()
 reading_task.cancel() asyncio.async(self.run_roulette(conn, other)) else: self.waiter.set_result(conn) ! yield from conn.wait_closed() ! return ws
  • 43. from jsonmodels import models, fields from jsonmodels.errors import ValidationError ! ! class StringChoiceField(fields.StringField): def __init__(self, choices=None, *args, **kw): self.choices = choices or [] super(StringChoiceField, self).__init__(*args, **kw) ! def validate(self, value): if value not in self.choices: raise ValidationError('invalid choice value') super(StringChoiceField, self).validate(value) ! class Jsep(models.Base): type = StringChoiceField(choices=['offer', 'answer'], required=True) sdp = fields.StringField(required=True) ! class Candidate(models.Base): candidate = fields.StringField(required=True) sdpMid = fields.StringField(required=True) sdpMLineIndex = fields.IntField(required=True) ! class YoPayload(models.Base): yo = fields.StringField(required=True) jsep = fields.EmbeddedField(Jsep) candidate = fields.EmbeddedField(Candidate)
  • 44. @asyncio.coroutine def run_roulette(self, peerA, peerB): log.info('Running roulette: %s, %s' % (peerA, peerB)) ! @asyncio.coroutine def close_connections(): yield from asyncio.wait([peerA.close(), peerB.close()],
 return_when=asyncio.ALL_COMPLETED) ! def parse(data): try: data = json.loads(data) payload = YoPayload(**data) payload.validate() except Exception as e: log.warning('Error parsing payload: %s' % e) return None return payload
  • 45. # request offer offer_request = YoPayload(yo='yo') peerA.write(json.dumps(offer_request.to_struct())) ! # get offer data = yield from peerA.read(timeout=READ_TIMEOUT) if not data: yield from close_connections() return ! offer = parse(data) if offer is None or offer.jsep is None or offer.jsep.type != 'offer': log.warning('Invalid offer received') yield from close_connections() return ! # send offer peerB.write(json.dumps(offer.to_struct()))
  • 46. # wait for answer data = yield from peerB.read(timeout=READ_TIMEOUT) if not data: yield from close_connections() return ! answer = parse(data) if answer is None or answer.jsep is None or answer.jsep.type != 'answer': log.warning('Invalid answer received') yield from close_connections() return ! # dispatch answer peerA.write(json.dumps(answer.to_struct()))
  • 47. # wait for candidates / end while True: peer_a_read = asyncio.async(peerA.read()) peer_a_read.other_peer = peerB peer_b_read = asyncio.async(peerB.read()) peer_b_read.other_peer = peerA done, pending = yield from asyncio.wait([peer_a_read, peer_b_read], return_when=asyncio.FIRST_COMPLETED) for task in pending: task.cancel() for task in done: data = task.result() if not data: break # all we can get at this point is trickled ICE candidates candidate = parse(data) if candidate is None or candidate.candidate is None: log.warning('Invalid candidate received!') break task.other_peer.write(json.dumps(candidate.to_struct())) else: continue break # close connections yield from close_connections()
  • 48.