SlideShare a Scribd company logo
WebRTC in Perl

{

Using Mojolicious




What
Why
How

WebRTC Rationale


Real-time Communication Between Browsers
Is Peer-to-Peer



http://www.html5rocks.com/en/tutorials/webrtc/basics/



What




Why

No plugin required
Completely browser based
Non-browser clients possible
How





How

Use signaling to exchange endpoint details
Signaling is the backend
Directly connect, if possible
Relay server used if nothing else works
#!/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>


Gist

https://gist.github.com/brianmed/6927400







$ 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
Screenshot of answerer

More Related Content

What's hot

Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkJeremy Kendall
 
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Arc & Codementor
 
Any event intro
Any event introAny event intro
Any event intro
qiang
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
Jeremy Kendall
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous
Shmuel Fomberg
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right Reasons
Matt Follett
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
Flavio Poletti
 
Nubilus Perl
Nubilus PerlNubilus Perl
Nubilus Perl
Flavio Poletti
 
The promise of asynchronous PHP
The promise of asynchronous PHPThe promise of asynchronous PHP
The promise of asynchronous PHP
Wim Godden
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
julien pauli
 
Slim RedBeanPHP and Knockout
Slim RedBeanPHP and KnockoutSlim RedBeanPHP and Knockout
Slim RedBeanPHP and Knockout
Vic Metcalfe
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Masahiro Nagano
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
Marcus Ramberg
 
Asynchronous I/O in PHP
Asynchronous I/O in PHPAsynchronous I/O in PHP
Asynchronous I/O in PHPThomas Weinert
 
YAPC::Asia 2010 Twitter解析サービス
YAPC::Asia 2010 Twitter解析サービスYAPC::Asia 2010 Twitter解析サービス
YAPC::Asia 2010 Twitter解析サービスYusuke Wada
 
React PHP: the NodeJS challenger
React PHP: the NodeJS challengerReact PHP: the NodeJS challenger
React PHP: the NodeJS challenger
vanphp
 
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
Yusuke Wada
 
Php functions
Php functionsPhp functions
Php functions
JIGAR MAKHIJA
 

What's hot (20)

Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
 
dotCloud and go
dotCloud and godotCloud and go
dotCloud and go
 
Perl5i
Perl5iPerl5i
Perl5i
 
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
 
Any event intro
Any event introAny event intro
Any event intro
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right Reasons
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
 
Nubilus Perl
Nubilus PerlNubilus Perl
Nubilus Perl
 
The promise of asynchronous PHP
The promise of asynchronous PHPThe promise of asynchronous PHP
The promise of asynchronous PHP
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
 
Slim RedBeanPHP and Knockout
Slim RedBeanPHP and KnockoutSlim RedBeanPHP and Knockout
Slim RedBeanPHP and Knockout
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
 
Asynchronous I/O in PHP
Asynchronous I/O in PHPAsynchronous I/O in PHP
Asynchronous I/O in PHP
 
YAPC::Asia 2010 Twitter解析サービス
YAPC::Asia 2010 Twitter解析サービスYAPC::Asia 2010 Twitter解析サービス
YAPC::Asia 2010 Twitter解析サービス
 
React PHP: the NodeJS challenger
React PHP: the NodeJS challengerReact PHP: the NodeJS challenger
React PHP: the NodeJS challenger
 
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
エロサイト管理者の憂鬱3 - Hokkaiodo.pm#4 -
 
Php functions
Php functionsPhp functions
Php functions
 

Similar to Webrtc mojo

RESTful API 제대로 만들기
RESTful API 제대로 만들기RESTful API 제대로 만들기
RESTful API 제대로 만들기
Juwon Kim
 
Managing State in React Apps with RxJS by James Wright at FrontCon 2019
Managing State in React Apps with RxJS by James Wright at FrontCon 2019Managing State in React Apps with RxJS by James Wright at FrontCon 2019
Managing State in React Apps with RxJS by James Wright at FrontCon 2019
DevClub_lv
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
Boris Dinkevich
 
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
Mateusz Zalewski
 
Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
Boris Dinkevich
 
C A S Sample Php
C A S Sample PhpC A S Sample Php
C A S Sample PhpJH Lee
 
Getting started with Elasticsearch and .NET
Getting started with Elasticsearch and .NETGetting started with Elasticsearch and .NET
Getting started with Elasticsearch and .NET
Tomas Jansson
 
Please teach me how to fix the errors and where should be modified. .pdf
Please teach me how to fix the errors and where should be modified. .pdfPlease teach me how to fix the errors and where should be modified. .pdf
Please teach me how to fix the errors and where should be modified. .pdf
amarndsons
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and Inference
Richard Fox
 
Windows Phone 8 Sensors
Windows Phone 8 SensorsWindows Phone 8 Sensors
Windows Phone 8 Sensors
David Isbitski
 
JSON and the APInauts
JSON and the APInautsJSON and the APInauts
JSON and the APInauts
Wynn Netherland
 
PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021
Ayesh Karunaratne
 
jSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession #4 - Maciej Puchalski - Zaawansowany retrofitjSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession
 
Going crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPGoing crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHP
Mariano Iglesias
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
Peter Friese
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silex
Michele Orselli
 
Embracing the-power-of-refactor
Embracing the-power-of-refactorEmbracing the-power-of-refactor
Embracing the-power-of-refactor
Xiaojun REN
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Ismael Celis
 

Similar to Webrtc mojo (20)

RESTful API 제대로 만들기
RESTful API 제대로 만들기RESTful API 제대로 만들기
RESTful API 제대로 만들기
 
Managing State in React Apps with RxJS by James Wright at FrontCon 2019
Managing State in React Apps with RxJS by James Wright at FrontCon 2019Managing State in React Apps with RxJS by James Wright at FrontCon 2019
Managing State in React Apps with RxJS by James Wright at FrontCon 2019
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
 
Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
 
C A S Sample Php
C A S Sample PhpC A S Sample Php
C A S Sample Php
 
Getting started with Elasticsearch and .NET
Getting started with Elasticsearch and .NETGetting started with Elasticsearch and .NET
Getting started with Elasticsearch and .NET
 
XQuery Rocks
XQuery RocksXQuery Rocks
XQuery Rocks
 
Please teach me how to fix the errors and where should be modified. .pdf
Please teach me how to fix the errors and where should be modified. .pdfPlease teach me how to fix the errors and where should be modified. .pdf
Please teach me how to fix the errors and where should be modified. .pdf
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and Inference
 
Winform
WinformWinform
Winform
 
Windows Phone 8 Sensors
Windows Phone 8 SensorsWindows Phone 8 Sensors
Windows Phone 8 Sensors
 
JSON and the APInauts
JSON and the APInautsJSON and the APInauts
JSON and the APInauts
 
PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021PHP Enums - PHPCon Japan 2021
PHP Enums - PHPCon Japan 2021
 
jSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession #4 - Maciej Puchalski - Zaawansowany retrofitjSession #4 - Maciej Puchalski - Zaawansowany retrofit
jSession #4 - Maciej Puchalski - Zaawansowany retrofit
 
Going crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPGoing crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHP
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silex
 
Embracing the-power-of-refactor
Embracing the-power-of-refactorEmbracing the-power-of-refactor
Embracing the-power-of-refactor
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
 

Recently uploaded

Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
g2nightmarescribd
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Tobias Schneck
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
DianaGray10
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 

Recently uploaded (20)

Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 

Webrtc mojo

  • 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>
  • 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