SlideShare ist ein Scribd-Unternehmen logo
1 von 10
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

Weitere ähnliche Inhalte

Was ist angesagt?

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
Jeremy Kendall
 
Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7Operation Oriented Web Applications / Yokohama pm7
Operation Oriented Web Applications / Yokohama pm7
Masahiro Nagano
 
Asynchronous I/O in PHP
Asynchronous I/O in PHPAsynchronous I/O in PHP
Asynchronous I/O in PHP
Thomas Weinert
 
YAPC::Asia 2010 Twitter解析サービス
YAPC::Asia 2010 Twitter解析サービスYAPC::Asia 2010 Twitter解析サービス
YAPC::Asia 2010 Twitter解析サービス
Yusuke Wada
 

Was ist angesagt? (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
 

Ähnlich wie Webrtc mojo

C A S Sample Php
C A S Sample PhpC A S Sample Php
C A S Sample Php
JH Lee
 
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
 
Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010Websockets talk at Rubyconf Uruguay 2010
Websockets talk at Rubyconf Uruguay 2010
Ismael Celis
 

Ähnlich wie 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
 

Kürzlich hochgeladen

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Kürzlich hochgeladen (20)

Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 

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