Your SlideShare is downloading. ×
Webrtc mojo
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Webrtc mojo

866
views

Published on

WebRTC DataChannel example in Perl and Mojolicious.

WebRTC DataChannel example in Perl and Mojolicious.

Published in: Technology, Business

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
866
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. WebRTC in Perl { Using Mojolicious
  • 2.    What Why How WebRTC Rationale
  • 3.  Real-time Communication Between Browsers Is Peer-to-Peer  http://www.html5rocks.com/en/tutorials/webrtc/basics/  What
  • 4.    Why No plugin required Completely browser based Non-browser clients possible
  • 5. How
  • 6.     How Use signaling to exchange endpoint details Signaling is the backend Directly connect, if possible Relay server used if nothing else works
  • 7. #!/OPT/PERL FUNCTION APPENDDIV(DATA) VAR DIV USE USE MOJOLICIOUS ::LITE; JSON; { = DOCUMENT.CREA TEELEMENT('DIV'); = DATA; FUNCTION RETURNSDP() { APPENDDIV("ANSWERER: SEND SDP"); DIV.INNER HTML SOCKET.SEND({ SENDER: 'ANSWERER', VAR CHATOUTPUT '/' => SUB { MY $SELF = SHIFT; = DOCUMENT.GE TELEME NTBYID('CHA T-OUTPUT'); SDP: ANSWERER.LOCALDES CRIP TION CHATOUTP UT.INS ERTBEFORE(DIV, CHATOUTPUT.FIRS TCHILD); GET }); } DIV.TABINDE X $SELF->RENDER("INDE X"); = 0; DIV.FOCUS(); }; IF (ISFIREFOX) } { ANSWERER.SETRE MOTE D ESCRIP TION(NEW MOZRTCS ESS ION DE SCRIP TION(OFFER SDP), FUNCTION() ANSWERER.CREATE ANSWE R(FUNCTION MY '/WSCHANNEL/:TYPE' => SUB { $SELF = SHIFT; MY $TYPE = $SELF->PARAM("TYPE "); VAR ICESERVERS WEBSOCKET ICESERVERS: ={ $SELF->APP->LOG->DEBUG("W EBSOCKET OPENED: }, ONERROR, }); $ID = MOJO::IOLOOP->RECURRING(4 => SUB { ("OFFERER" EQ $TYPE) { IF (- F "/TMP/SDP.ANSWERER") { $SELF->APP->LOG->DEBUG("SENDING SDP: TO OFFERER FROM ANSWERER"); MY $TXT = MOJO::UTIL::SLURP("/TMP/SDP.ANSWERE R"); MY $REF = JSON::FROM_JSON($TX T); $SELF->SEND({JSON => $REF}); UNLINK ("/TMP/SDP.ANSWERER"); MOJO::UTIL::SPURT(SCA LAR LOCALTIME(TIME), "/TMP/SDP.OFFERER.SENT"); } OPTIONAL: ={ [{DTLSSRTPK EYA GREEMENT: {RTPDA TAC HA NNE LS: TRUE }] ={ [], { OFFERTORECE IVE AUDIO: OFFERTORECE IVE V IDEO: VAR MEDIACONS TRA INTS VAR CHATINPUT IF (E.KEYCODE APPENDDIV(THIS.VALUE); FUNCTION SETCHANNEL EV ENTS ( CHANNEL, CHANNELNA MEF OR CONSOLEOUTP UT) CHANNEL.ONERROR FALSE = ONERROR; OFFERER MOZRTCPE ERC ONNECTION(ICES ERV ERS, OPTIONA L RTPD A TA CHANNELS ); = NEW WEBKITRTCPEE RC ONNECTION(ICESE RV ERS, OPTIONAL R TPD A TA CHA NNELS ); = FUNCTION () { CONSOLE.LOG("CHANNEL: ONOPEN"); } DOCUMENT.GETELE ME NTB Y ID('CHA T- INP UT').DIS ABLED ELSE { OFFERER = FALSE; }; } } = OFFERER.CREATED A TA CHANNEL('RTCD A TA CHANNEL', { RELIABLE : TRUE { VAR URL; IF }); ("OFFERER" == TYPE) { URL = "<%= URL_FOR('/WSCHANNEL/OFFERE R')->TO_AB S->SCHEME('WS') %>"; } CONNECTION FROM OFFERER"); = OFFERERDATAC HANNEL; ELSE CONSOLE.LOG("CONSOLE : OFFERER"); { URL = "<%= URL_FOR('/WSCHANNEL/ANSWERER')->TO_ ABS->SCHE ME('WS') %>"; } SETCHANNEL EVE NTS (OFFERER DA TAC HANNEL, 'OFFERER'); CONSOLE.LOG("CONNECTING: SOCKET = FUNCTION (EVENT) { CONSOLE.LOG("ONICECANDIDA TE : OFFERER"); IF (EVENT.CANDIDA TE ) SENDCANDIDA TE (EVE NT.CANDIDA TE ); IF (!EVENT.CANDIDA TE ) RETURNSDP(); FROM OFFERER"); " + URL); = NEW W EBSOCKET(URL); = FUNCTION () { " + URL); SOCKET.ONOPEN APPENDDIV("CONNECTED: }; SOCKET.ONMESSA GE = FUNCTION (E) { = JSON.PARSE(E.DATA); " + DATA.SENDER); { == 'OFFERER') { APPENDDIV("RECV: SDP : OFFERER"); CREATEANSWER(DA TA. SDP); }; VAR DATA CONSOLE.LOG("ONMESSA GE : FUNCTION SENDCANDIDA TE () { IF (DATA.SDP) APPENDDIV("OFFERER: SEND CANDIDA TE "); IF (DATA.SENDER SOCKET.SEND({ SENDER: 'OFFERER', } CANDIDATE : EVENT.CANDIDA TE } } }); ELSE }); } $SELF->ON(MESSAGE => SUB { MY ($SELF, $MSG) = @_; FUNCTION RETURNSDP() { APPENDDIV("RECV: SDP : ANSWERER"); IF (ISFIREFOX) { APPENDDIV("OFFERER: SEND SDP"); SOCKET.SEND({ SENDER: 'OFFERER', SDP: OFFERER.LOCALDE SCRIP TION }); $TYPE"); ($$RET{SENDER} && "OFFERER" EQ $$RET{SENDER} && $$RET{SDP}) { MOJO::UTIL::SPURT($MSG, "/TMP/SDP.OFFERER"); ELSE OFFERER.CREATE OFFER(FUNCTION } (SESSIONDES CRIP TION) { OFFERER.SETLOCA LD ESCRIP TION(SE SS ION DES CRIP TION); }, ONERROR, MEDIA CONS TRA INTS); FUNCTION ONERROR( ERR) { CONSOLE.LOG(ERR); } FUNCTION CREATEANSWER(OFFER SDP) { { ANSWERER = NEW MOZRTCP EER CONNE CTION( ICE SERVE RS , IF (ISFIREFOX) OPTIONAL R TP DA TAC HANNE LS ); } ELSE { = NEW WEBKITRTCP EER CONNE CTION(ICE SERVE RS, ANSWERERDATA CHA NNE L OPTIONAL RTP DA TAC HANNELS ); IF = ANSWERER.CREA TED A TA CHANNEL('RTCD A TA CHANNEL', { RELIABLE : TRUE }); SETCHANNEL EVE NTS (ANSWERE RD A TA CHANNEL, 'ANSWERER'); CONNECTION $CODE."); = ANSWERERDATA CHANNEL; CONSOLE.LOG("CONSOLE : ANSWER"); ANSWERER.ONICECANDIDA TE = FUNCTION (EVENT) { CONSOLE.LOG("ONICECANDIDA TE : ANSWERER"); }; IF (EVENT.CANDIDA TE ) SENDCANDIDA TE (); IF (!EVENT.CANDIDA TE ) RETURNSDP(); APP->START; }; __DATA__ FUNCTION SENDCANDIDA TE () } SOCKET.PUSH SOCKET.SEND SOCKET.SEND({ }); = SOCKET.SEND; = FUNCTION (DATA ) { " + DATA .SENDER); CONSOLE.LOG("SEND: SENDER: 'ANSWERER', CANDIDATE : EVENT.CANDIDA TE } ("ANSWERER" === DATA.SENDER && DATA.CANDIDA TE) { APPENDDIV("RECV: CANDIDA TE : ANSWERER"); IF (ISFIREFOX) { OFFERER.ADDICECANDIDA TE (NEW MOZRTCICECA NDIDA TE ({ SDPMLINEINDE X: DATA .CANDIDA TE .SDP ML INEINDE X, CANDIDATE: DATA.CANDIDA TE .CANDIDA TE })); } ELSE { OFFERER.ADDICECANDIDA TE (NEW RTCICECA NDIDA TE ({ SDPMLINEINDE X: DATA .CANDIDA TE .SDP ML INEINDE X, CANDIDATE: DATA.CANDIDA TE .CANDIDA TE })); } }; { APPENDDIV("ANSWERER: SEND CANDIDA TE"); @@ INDEX.HTML.EP ("OFFERER" === DATA.SENDER && DATA.CANDIDA TE) { APPENDDIV("RECV: CANDIDA TE : OFFERER"); IF (ISFIREFOX) { ANSWERER.ADDICECANDIDA TE (NEW MOZRTCICE CANDIDA TE ({ SDPMLINEINDE X: DATA .CANDIDA TE .SDP ML INEINDE X, CANDIDATE: DATA.CANDIDA TE .CANDIDA TE })); } ELSE { ANSWERER.ADDICECANDIDA TE (NEW RTCICECANDIDA TE ({ SDPMLINEINDE X: DATA .CANDIDA TE .SDP ML INEINDE X, CANDIDATE: DATA.CANDIDA TE .CANDIDA TE })); } } ANSWERER } }); CLOSED WITH STATUS RTCSES S IOND ESCRIP TION(DA TA.SDP)); } } } ($$RET{SENDER} && $$RET{CANDIDA TE}) { FOREACH MY $SUFFIX (QW (001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 END)) { IF ("END" EQ $SUFFIX) { $SELF->APP->LOG->DEBUG("W E ARE OUT OF CANDIDA TE SUFFIXES."); LAST; } MY $F = "/TMP/CANDIDA TE .$$RE T{SENDER}.$SUFFIX"; IF (-F $F) { NEXT; } MOJO::UTIL::SPURT($MS G, $F); LAST; } { OFFERER.SETREMOTE DE SCRIP TION(NEW } IF ($$RET{SENDER} && "ANSWERER" EQ $$RET{SENDER} && $$RET{SDP}) { MOJO::UTIL::SPURT($MSG, "/TMP/SDP.ANSWERER"); } { OFFERER.SETREMOTE DE SCRIP TION(NEW MOZRTCSE SS IOND ES CRIP TION(DA TA.SDP)); } } } <SCRIPT> VAR ISFIREFOX = !!NAVIGATOR.MOZGE T USER ME DIA; VAR CONNECTION; + EVENT.DATA); SOCKET.PUSH(JSON.S TRINGIFY (DA TA)); }; } </SCRIPT> Code – 350 lines!! = ''; THIS.FOCUS(); }; CHANNEL.ONOPEN OFFERERDATA CHANNEL $SELF->ON(FINISH => SUB { MY ($SELF, $CODE, $REASON) = @_; $SELF->APP->LOG->DEBUG("W EBSOCKET MOJO::IOLOOP->REMOVE($ID); UNLINK ("/TMP/SDP.$TYPE "); }); A MESSAGE :' </SCRIPT> { = NEW OFFERER.ONICECANDIDA TE IF THIS.VALUE + 'RECEIVED { IF (ISFIREFOX) } IF = FUNCTION (EVENT) { CONSOLE.LOG("CHANNEL: ONMESSAGE "); APPENDDIV(CHANNEL NAMEF OR CONSOLEOUTP UT }; } IF CONSOLE.LOG(CONNECTION); CONNECTION.SEND(THIS.VALUE); CHANNEL.ONMESSAGE VAR OFFERER, ANSWERER, ANSWERERDA TA CHA NNE L, OFFERERDA TA CHA NNEL; ELSE TYPE: { } }; ANSWERER"); = DOCUMENT.GE TELE MENTB YID('CHA T-INPUT'); = FUNCTION(E) { !== 13 || !THIS.VALUE) RETURN; CHATINPUT.ONKE YP RES S } FALSE, FUNCTION CONNECTS IGNALER( TYP E ) (- F "/TMP/SDP.OFFERER.SENT") { FOREACH MY $F (GLOB("/TMP/CANDIDA TE .OFFERE R.*")) { $SELF->APP->LOG->DEBUG("SENDING $F: TO ANSWERER MY $TXT = MOJO::UTIL::SLURP($F); MY $REF = JSON::FROM_JSON($ TXT); $SELF->SEND({JSON => $REF}); UNLINK($F); } UNLINK ("/TMP/SDP.OFFE RER.SE NT"); { MANDATORY : } $SELF->APP->LOG->DEBUG("MSG: $MSG: MY $RET = JSON::FROM_JSON($MS G); FUNCTION() MEDIACONS TRA INTS ); } OPTIONAL: FOREACH MY { (- F "/TMP/SDP.OFFERER") { MY $TXT = MOJO::UTIL::SLURP("/TMP/SDP.OFFERER"); MY $REF = JSON::FROM_JSON($TX T); $SELF->APP->LOG->DEBUG("SENDING SDP: TO ANSWERER $SELF->SEND({JSON => $REF}); UNLINK ("/TMP/SDP.OFFE RER "); RTCS ESS ION DES CRIP TION(OFFER SDP), (SESSIONDESCRIP TION) { ANSWERER.SETLOCA LDE SCRIP TION(SE SS ION DES CRIP TION); }, ONERROR, }, ONERROR); FUNCTION CREATEOFFE R() $F (GLOB("/TMP/CANDIDA TE.ANSWERE R.*")) { $SELF->APP->LOG->DEBUG("SENDING $F: TO OFFERER FROM MY $TXT = MOJO::UTIL::SLURP($F); MY $REF = JSON::FROM_JSON($TX T); $SELF->SEND({JSON => $REF}); UNLINK ($F); ANSWERER.CREATE ANSWE R(FUNCTION TRUE}, }; IF IF { ANSWERER.SETRE MOTE D ESCRIP TION(NEW VAR OPTIONA L RTPD A TA CHANNELS IF MEDIACONS TRA INTS ); } ELSE $TYPE"); # INCREASE INACTIV ITY TIMEOUT FOR CONNECTION A BIT MOJO::IOLOOP->STREAM($SELF->TX->CONNE CTION)->TIME OUT(300); MY (SESSIONDESCRIP TION) { ANSWERER.SETLOCA LDE SCRIP TION(SE SS ION DES CRIP TION); [{ URL: 'STUN:23.21.150.121' }] }; { HAS WORKED IN CHROME.<BR /> CREATE OFFER SHOULD BE CLICKED BY THE "OFFERER".<BR /> <BUTTON ID="CONNECT-OFFE RER ">CONNECT AS OFFERER</BUTTON> <BUTTON ID="CONNECT-ANSWERE R">CONNECT AS ANSWERER</BUTTON><BR /> <BUTTON ID="CREATE-OFFER">C REA TE OFFER</BUTTON> <INPUT TYPE="TE XT" ID="CHAT-INPUT" STYLE="FONT-S IZE: 1.2EM;" PLACEHOLDER="CHA T <DIV ID="CHAT-OUTPUT"></DIV> <SCRIPT> DOCUMENT.GE TE LE MENTB YID('CONNE CT-OFFERE R').ONCLICK = FUNCTION () { THIS.DISAB LED = TRUE; CONNECTS IGNALE R("OFFERE R"); }; DOCUMENT.GE TE LE MENTB YID('CONNE CT-ANSWE RER').ONCLICK = FUNCTION () { THIS.DISAB LED = TRUE; CONNECTS IGNALE R("ANSWE RER "); }; DOCUMENT.GE TE LE MENTB YID('CREA TE-OFFE R').ONCLICK = FUNCTION () { CREATEOFFER(); }; MESSAGE " DISABLED>
  • 8.  Gist https://gist.github.com/brianmed/6927400
  • 9.     $ perl datachannel.pl daemon Luanch two instances of chrome; perhaps stable and canary Click answerer in one window; offerer in the other; then click Create Offer in offerer window Chat session should initiate Run me
  • 10. Screenshot of answerer

×