networked-aframe
Version:
A web framework for building multi-user virtual reality experiences.
149 lines (118 loc) • 3.81 kB
JavaScript
/* global NAF */
const NoOpAdapter = require('./NoOpAdapter');
class WsEasyRtcInterface extends NoOpAdapter {
constructor(easyrtc) {
super();
this.easyrtc = easyrtc || window.easyrtc;
this.app = 'default';
this.room = 'default';
this.destination = {targetRoom: this.room};
this.connectedClients = [];
this.serverTimeRequests = 0;
this.timeOffsets = [];
this.avgTimeOffset = 0;
}
setServerUrl(url) {
this.serverUrl = url;
this.easyrtc.setSocketUrl(url);
}
setApp(appName) {
this.app = appName;
}
setRoom(roomName) {
this.room = roomName;
this.destination.targetRoom = this.room;
this.easyrtc.joinRoom(roomName, null);
}
setWebRtcOptions(options) {
// No webrtc support
}
setServerConnectListeners(successListener, failureListener) {
this.connectSuccess = successListener;
this.connectFailure = failureListener;
}
setRoomOccupantListener(occupantListener){
this.easyrtc.setRoomOccupantListener(function(roomName, occupants, primary) {
occupantListener(occupants);
});
}
setDataChannelListeners(openListener, closedListener, messageListener) {
this.openListener = openListener;
this.closedListener = closedListener;
this.easyrtc.setPeerListener(messageListener);
}
updateTimeOffset() {
const clientSentTime = Date.now() + this.avgTimeOffset;
return fetch(document.location.href, { method: "HEAD", cache: "no-cache" })
.then(res => {
var precision = 1000;
var serverReceivedTime = new Date(res.headers.get("Date")).getTime() + (precision / 2);
var clientReceivedTime = Date.now();
var serverTime = serverReceivedTime + ((clientReceivedTime - clientSentTime) / 2);
var timeOffset = serverTime - clientReceivedTime;
this.serverTimeRequests++;
if (this.serverTimeRequests <= 10) {
this.timeOffsets.push(timeOffset);
} else {
this.timeOffsets[this.serverTimeRequests % 10] = timeOffset;
}
this.avgTimeOffset = this.timeOffsets.reduce((acc, offset) => acc += offset, 0) / this.timeOffsets.length;
if (this.serverTimeRequests > 10) {
setTimeout(() => this.updateTimeOffset(), 5 * 60 * 1000); // Sync clock every 5 minutes.
} else {
this.updateTimeOffset();
}
});
}
connect() {
Promise.all([
this.updateTimeOffset(),
new Promise((resolve, reject) => {
this.easyrtc.connect(this.app, resolve, reject);
})
]).then(([_, clientId]) => {
this.connectSuccess(clientId);
}).catch(this.connectFailure);
}
shouldStartConnectionTo(clientId) {
return true;
}
startStreamConnection(clientId) {
this.connectedClients.push(clientId);
this.openListener(clientId);
}
closeStreamConnection(clientId) {
var index = this.connectedClients.indexOf(clientId);
if (index > -1) {
this.connectedClients.splice(index, 1);
}
this.closedListener(clientId);
}
sendData(clientId, dataType, data) {
this.easyrtc.sendDataWS(clientId, dataType, data);
}
sendDataGuaranteed(clientId, dataType, data) {
this.sendData(clientId, dataType, data);
}
broadcastData(dataType, data) {
this.easyrtc.sendDataWS(this.destination, dataType, data);
}
broadcastDataGuaranteed(dataType, data) {
this.broadcastData(dataType, data);
}
getConnectStatus(clientId) {
var connected = this.connectedClients.indexOf(clientId) != -1;
if (connected) {
return NAF.adapters.IS_CONNECTED;
} else {
return NAF.adapters.NOT_CONNECTED;
}
}
getServerTime() {
return Date.now() + this.avgTimeOffset;
}
disconnect() {
this.easyrtc.disconnect();
}
}
module.exports = WsEasyRtcInterface;