index.html
codice:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Una semplice video chat p2p</title>
</head>
<body>
<video width="300" id="video_locale" autoplay="autoplay"></video>
<video width="300" id="video_remoto" autoplay="autoplay"></video>
<script src="javascript/application2.js"></script>
</body>
</html>
js/application.js
codice:
// --- gestione del prefisso sperimentale ---
window.RTCPeerConnection = window.webkitRTCPeerConnection;
navigator.getUserMedia = navigator.webkitGetUserMedia ;
window.URL = window.URL || window.webkitURL;
// --- variabili iniziali ---
var video_locale = document.getElementById("video_locale"),
video_remoto = document.getElementById("video_remoto"),
ws = new WebSocket('ws://__IP_SERVER_WEBSOCKET__:8080'),
peer;
if(location.hash === ""){
// in questo caso l'URL non contiene la chiave e devo crearne una
var stanza = Math.round(Math.random()*1000),
chiamante = 0;
location.hash = stanza;
}else{
// in questo caso l'URL contiene già la chiave
var stanza = location.hash.substr(1),
chiamante = 1;
}
// --- init dall'applicazione all'apertura del canale websocket ---
ws.addEventListener('open', function(){
// invio al server websocket l'identificativo del canale di
// comunicazione al quale mi voglio connettere.
ws.send("c:" + stanza);
inizializza_video(); // dobbiamo ancora scrivere questa funzione.
}, false);
// --- configurazione ---
var mediaConstraints = {'mandatory': {'OfferToReceiveAudio':true, 'OfferToReceiveVideo':true }};
var peer_config = {"iceServers": [{"url": "stun:stunserver.org"}]};
// --- richiesta accesso webcam e microfono e init della connessione P2P ---
function inizializza_video() {
navigator.getUserMedia( {'audio':true, 'video':true},
function(stream) {
video_locale.src = URL.createObjectURL(stream);
peer = new RTCPeerConnection(peer_config);
peer.onicecandidate = onIceCandidate;
peer.onaddstream = function(event){
video_remoto.src = URL.createObjectURL(event.stream);
};
peer.addStream(stream);
if (chiamante)
peer.createOffer(sdpcreato, null, mediaConstraints);
}
);
}
// --- invio l'SDP al peer ---
function sdpcreato(sdp) {
peer.setLocalDescription(sdp);
messaggio_da_inviare(sdp);
}
// --- invio il candidato ICE al peer ---
function onIceCandidate(event) {
if (event.candidate) {
messaggio_da_inviare(event.candidate);
}
}
// --- invio messaggi al websocket ---
function messaggio_da_inviare(msg) {
var msgjson = JSON.stringify(msg);
ws.send("m:"+ stanza + ":" + chiamante + ":" + msgjson);
}
// --- ricezione messaggi dal websocket ---
ws.addEventListener('message', function(evt){
var msg = evt.data;
if(parseInt(msg.substr(0,1),10) !== chiamante){
processa(msg.substr(2));
}
});
// --- interpretazione dei messaggi ricevuti per stabilire la connessione P2P ---
function processa(messaggio) {
var msg = JSON.parse(messaggio);
if (msg.type === 'offer') {
peer.setRemoteDescription(new RTCSessionDescription(msg));
peer.createAnswer(sdpcreato, null, mediaConstraints);
} else if (msg.type === 'answer') {
peer.setRemoteDescription(new RTCSessionDescription(msg));
} else {
var candidate = new RTCIceCandidate(msg);
peer.addIceCandidate(candidate);
}
}
RUBY - webserver.rb
codice:
require 'rubygems'
require 'em-websocket'
EventMachine.run do
@channels = {}
EventMachine::WebSocket.start(
:host => "127.0.0.1", :port => 8080) do |ws|
ws.onmessage do |msg|
command, params = msg.split(":",2)
if(command == "c")
@channels[msg[2..-1]] ||= EM::Channel.new
@channels[msg[2..-1]].subscribe{ |msg| ws.send msg }
else
room, message = params.split(":",2)
@channels[room].push message
end
end
end
end