WebRTC audio/video call and conferencing server.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

240 lines
5.2 KiB

/*
* Spreed WebRTC.
* Copyright (C) 2013-2014 struktur AG
*
* This file is part of Spreed WebRTC.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) {
var timeout = 5000;
var timeout_max = 20000;
var Connector = function(version) {
this.version = version;
this.e = $({});
this.error = false;
this.connected = false;
this.disabled = false;
this.connecting = null;
this.connecting_timeout = timeout;
this.token = null;
this.queue = [];
this.roomid = null;
var ua = uaparser();
if (ua.os.name && /Spreed Desktop Caller/i.test(ua.ua)) {
this.userAgent = ua.ua.match(/Spreed Desktop Caller\/([\d.]+)/i)[1] + " (" + ua.os.name + ")";
} else if (ua.browser.name) {
this.userAgent = ua.browser.name + " " + ua.browser.major;
} else {
this.userAgent = ua.ua;
}
};
Connector.prototype.connect = function(url) {
//console.log("connect", this.disabled, url);
if (this.disabled) {
return;
}
this.error = false;
this.e.triggerHandler("connecting", [url]);
this.url = url;
if (this.token) {
url += ("?t=" + this.token);
//console.log("Reusing existing token", this.token);
}
var conn = this.conn = new WebSocket(url);
conn.onopen = _.bind(this.onopen, this);
conn.onerror = _.bind(this.onerror, this);
conn.onclose = _.bind(this.onclose, this);
conn.onmessage = _.bind(this.onmessage, this)
this.connecting = window.setTimeout(_.bind(function() {
console.warn("Connection timeout out after", this.connecting_timeout);
if (this.connecting_timeout < timeout_max) {
this.connecting_timeout += timeout;
}
this.e.triggerHandler("error");
this.reconnect();
}, this), this.connecting_timeout);
};
Connector.prototype.reconnect = function() {
if (!this.url) {
return;
}
this.close();
var url = this.url;
this.url = null;
setTimeout(_.bind(function() {
this.connect(url);
}, this), 200);
};
Connector.prototype.close = function() {
this.connected = false;
if (this.conn) {
var conn = this.conn;
this.conn = null;
if (!this.error) {
conn.close();
}
conn.onopen = conn.onerror = conn.onclose = conn.onmessage = null;
}
};
Connector.prototype.forgetAndReconnect = function() {
this.token = null;
if (this.conn && this.connected) {
this.conn.close();
}
};
Connector.prototype.room = function(roomid, cb) {
var was_connected = this.connected;
if (was_connected) {
if (this.roomid === roomid) {
return;
}
this.e.triggerHandler("closed", [{
soft: true
}]);
}
this.roomid = roomid;
roomid = this.roomid ? this.roomid : "";
if (cb) {
cb();
}
this.send({
Type: "Hello",
Hello: {
Version: this.version,
Ua: this.userAgent,
Id: roomid
}
});
if (was_connected) {
this.e.triggerHandler("open", [{
soft: true
}]);
}
};
Connector.prototype.onopen = function(event) {
window.clearTimeout(this.connecting);
this.connecting_timeout = timeout;
//console.log("onopen", event);
console.info("Connector on connection open.");
this.room(this.roomid, _.bind(function() {
this.connected = true;
}, this));
this.e.triggerHandler("open", [event]);
// Send out stuff which was previously queued.
var data;
while (this.queue.length > 0 && this.connected) {
data = this.queue.shift();
this.send(data);
}
};
Connector.prototype.onerror = function(event) {
window.clearTimeout(this.connecting);
this.connecting_timeout = timeout;
//console.log("onerror", event);
console.warn("Connector on connection error.");
this.error = true;
this.close();
this.e.triggerHandler("error", [event]);
};
Connector.prototype.onclose = function(event) {
window.clearTimeout(this.connecting);
this.connecting_timeout = timeout;
//console.log("onclose", event);
console.info("Connector on connection close.", event);
this.close();
if (!this.error) {
this.e.triggerHandler("close", [event]);
}
this.e.triggerHandler("closed", [event]);
};
Connector.prototype.onmessage = function(event) {
//console.log("onmessage", event);
var msg = JSON.parse(event.data);
this.e.triggerHandler("received", [msg]);
};
Connector.prototype.send = function(data, noqueue) {
if (!this.connected) {
if (!noqueue) {
this.queue.push(data);
console.warn("Queuing sending data because of not connected.", data);
return;
}
}
this.conn.send(JSON.stringify(data));
};
Connector.prototype.ready = function(func) {
/* Call a function whenever the Connection is ready */
this.e.on("open", func);
if (this.connected) {
func();
}
};
return Connector;
});