Skip to content

Commit 45a3972

Browse files
committed
Merge pull request #12 from rtc-io/unsupported-browsers
Provides support for browsers using the Temasys plugin, and "unsupported" browsers
2 parents 1a5aa8e + 47d7f0b commit 45a3972

File tree

10 files changed

+255
-35
lines changed

10 files changed

+255
-35
lines changed

example/basic.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ var quickconnect = require('rtc-quickconnect');
22
var health = require('../');
33
var crel = require('crel');
44
var xhr = require('xhr');
5-
var qc = quickconnect('http://rtc.io/switchboard/', {
5+
var qc = quickconnect('http://rtc.io/switchboard/', {
66
room: 'healthexp',
7-
sdpfilter: function(sdp) { append(sdp); return sdp; }
7+
sdpfilter: function(sdp) { append(sdp); return sdp; }
88
});
99

1010
var monitor = health(qc, { pollInterval: 10000 });

example/temasys-basic.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
var quickconnect = require('rtc-quickconnect');
2+
var plugins = [require('rtc-plugin-temasys')];
3+
var health = require('../');
4+
var crel = require('crel');
5+
var qc = quickconnect('http://rtc.io/switchboard/', {
6+
room: 'health-temasys-test',
7+
sdpfilter: function(sdp) { append(sdp); return sdp; },
8+
plugins: plugins
9+
});
10+
11+
var monitor = health(qc, { pollInterval: 10000 });
12+
13+
var logger = crel('div');
14+
document.body.appendChild(logger);
15+
function append(msg) {
16+
crel(logger, crel('p', msg));
17+
}
18+
19+
qc.on('channel:opened', function(id, dc) {
20+
console.log(arguments)
21+
append('channel opened ' + id);
22+
dc.onmessage = function(msg) {
23+
if (msg && msg.data) append(msg.data);
24+
};
25+
26+
function ping() {
27+
console.log('ping');
28+
dc.send(new Date().toUTCString() + ' - ping');
29+
setTimeout(ping, 1000);
30+
}
31+
32+
if (dc.readyState !== 'open') {
33+
dc.onopen = ping;
34+
} else {
35+
ping();
36+
}
37+
});
38+
39+
var filter = ['bytesReceived', 'bytesSent'];
40+
var types = ['googComponent', 'googCandidatePair'];
41+
42+
monitor.on('health:changed', function(iceConnectionState, pc) {
43+
append('iceConnectionState - ' + iceConnectionState);
44+
});
45+
46+
monitor.on('health:closed', function(pc) {
47+
append('peer left');
48+
});
49+
50+
monitor.on('health:report', function(reporter, pc) {
51+
52+
var statistics = [];
53+
54+
console.log(reporter.id);
55+
console.log(reporter.isActive() ? 'Connection is active' : 'Connection is inactive');
56+
57+
var channels = reporter.getChannelReports();
58+
59+
for (var i = 0; i < channels.length; i++) {
60+
var report = channels[i];
61+
console.log(report.toJSON());
62+
}
63+
});
64+
65+
qc.createDataChannel('chat', {ordered: true});
66+
67+
append('started');

example/temasys-video.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
var quickconnect = require('rtc-quickconnect');
2+
var captureConfig = require('rtc-captureconfig');
3+
var capture = require('rtc-capture');
4+
var attach = require('rtc-attach');
5+
var health = require('../');
6+
var crel = require('crel');
7+
var plugins = [require('rtc-plugin-temasys')];
8+
var constraints = captureConfig('camera min:1280x720').toConstraints();
9+
10+
function attachVideo(stream, el) {
11+
attach(stream, {
12+
el: el,
13+
plugins: plugins
14+
}, function(err, el) {
15+
if (err || !el) return;
16+
document.body.appendChild(el);
17+
});
18+
}
19+
20+
capture(constraints, {plugins: plugins}, function(err, stream) {
21+
22+
attachVideo(stream, crel('div', { class: 'local', style: 'width: 50%;' }));
23+
24+
var qc = window.qc =
25+
quickconnect('http://rtc.io/switchboard/', {
26+
room: 'health-temasys-capture',
27+
iceServers: [
28+
{ url: 'stun:stun.l.google.com:19302' }
29+
],
30+
disableHeartbeat: true,
31+
plugins: [require('rtc-plugin-temasys')]
32+
}).addStream(stream)
33+
.on('stream:added', function(id, stream) {
34+
console.log('added %s', id);
35+
var el = crel('div', { class: 'remote', id: id , style: 'width: 50%;'});
36+
attachVideo(stream, el);
37+
})
38+
.on('stream:removed', function(id) {
39+
console.log('removed %s', id);
40+
var el = document.getElementById(id);
41+
if (el) el.remove();
42+
})
43+
.on('local:announce', function(data) {
44+
console.log('-> connected to %s', data.room);
45+
})
46+
.on('peer:announce', function(data) {
47+
console.log('-> announce');
48+
console.log(data);
49+
});
50+
51+
var monitor = health(qc, { pollInterval: 2500, verbose: true });
52+
var previous = null;
53+
monitor.on('health:report', function(reporter) {
54+
55+
var statistics = [];
56+
// console.log(reporter.isActive() ? 'Connection is active' : 'Connection is inactive');
57+
// var channels = reporter.getChannelReports();
58+
// for (var i = 0; i < channels.length; i++) {
59+
// var report = channels[i];
60+
// console.log(report.toJSON());
61+
// }
62+
previous = reporter.toJSON({
63+
exclude: ['googTrack', 'googComponent', 'googCertificate', 'googLibjingleSession'],
64+
compareTo: previous
65+
});
66+
console.log(previous);
67+
});
68+
69+
monitor.on('health:notify', function(evt, opts, data) {
70+
// console.log('[%s->%s] %s', opts.source, opts.about, evt);
71+
// if (data) {
72+
// console.log(JSON.stringify(data));
73+
// }
74+
});
75+
76+
monitor.on('health:connection:status', function(conn, status, previousStatus) {
77+
console.log('Status changed from %s to %s', previousStatus, status);
78+
});
79+
80+
window.monitor = monitor;
81+
});

index.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ var Reporter = require('./lib/reporter');
66
var MonitoredConnection = require('./lib/connection').MonitoredConnection;
77
var error = require('./lib/error');
88
var util = require('./lib/util');
9-
var provider = require('./lib/provider');
9+
var detectProvider = require('./lib/provider');
1010
var wildcard = require('wildcard');
1111

1212
var OPTIONAL_MONITOR_EVENTS = [
@@ -39,20 +39,21 @@ var OPTIONAL_MONITOR_EVENTS = [
3939
**/
4040
module.exports = function(qc, opts) {
4141

42-
if (!provider) {
43-
console.log('WARNING! No WebRTC provider detected - rtc-health is disabled');
44-
return;
45-
}
46-
4742
opts = opts || {};
4843

44+
var provider = null;
4945
var emitter = new EventEmitter();
5046
emitter.pollInterval = opts.pollInterval || 1000;
5147
var connections = {};
5248
var timers = {};
5349
var logs = {};
5450

5551
function log(peerId, pc, data) {
52+
// A provider must be present for logging to be enabled
53+
if (!provider) {
54+
return;
55+
}
56+
5657
provider.getStats(pc, null, function(err, reports) {
5758
var tc = connections[data.id];
5859

@@ -194,5 +195,20 @@ module.exports = function(qc, opts) {
194195
return connections && connections[target];
195196
};
196197

198+
// Provider detection
199+
function detect() {
200+
provider = detectProvider();
201+
if (!provider) {
202+
console.log('WARNING! No WebRTC provider detected - rtc-health is disabled until a provider is detected');
203+
}
204+
}
205+
206+
// In the case of some plugins, we don't get notified that it's using a plugin, and
207+
// have no means to reasonably identify the existence of a plugin
208+
// So as a final fallback, rerun the detection on a local announce
209+
qc.once('local:announce', detect);
210+
211+
// Attempt to detect initially
212+
detect();
197213
return emitter;
198214
};

lib/provider.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
/**
22
Detects and loads the correct provider for this browser
33
**/
4-
var providers = [ require('./providers/google'), require('./providers/mozilla') ];
4+
var providers = [
5+
require('./providers/google'),
6+
require('./providers/mozilla'),
7+
require('./providers/temasys'),
8+
require('./providers/unsupported'),
9+
];
510

6-
// Check for the existing of the RTCPeerConnection
7-
for (var i = 0; i < providers.length; i++) {
8-
var pv = providers[i];
9-
var RTCPeerConnection = window[pv.RTC_PREFIX + 'RTCPeerConnection'];
10-
if (RTCPeerConnection) {
11-
module.exports = pv;
12-
break;
11+
module.exports = function() {
12+
var detected = null;
13+
14+
// Check for the existing of the RTCPeerConnection
15+
for (var i = 0; i < providers.length; i++) {
16+
var pv = providers[i];
17+
var RTCPeerConnection = window[(pv.RTC_PREFIX || '') + 'RTCPeerConnection'];
18+
if (RTCPeerConnection || (pv.check && pv.check())) {
19+
detected = pv;
20+
break;
21+
}
1322
}
14-
}
23+
24+
return detected;
25+
};

lib/providers/google.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ exports.id = 'chrome';
1111
Gets the RTCStats for a given RTCPeerConnection
1212
**/
1313
exports.getStats = function(pc, opts, callback) {
14-
pc.getStats(function(stats) {
14+
pc.getStats(function(stats) {
1515
if (!stats) return callback('Could not getStats');
1616
var result = stats.result();
1717
var reports = [];
@@ -28,8 +28,8 @@ exports.getStats = function(pc, opts, callback) {
2828
function convertToStatsReport(report, compare) {
2929
if (!report) return null;
3030

31-
var result = new StatsReport({
32-
id: report.id,
31+
var result = new StatsReport({
32+
id: report.id,
3333
type: util.standardizeKey(FIELD_PREFIX, report.type),
3434
subType: (report.type === 'ssrc' ? (report.id.indexOf('send') > 0 ? 'send' : 'receive') : undefined),
3535
timestamp: report.timestamp

lib/providers/temasys.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
var google = require('./google');
2+
3+
/**
4+
Temasys WebRTC Provider
5+
**/
6+
exports.id = 'temasys';
7+
8+
/**
9+
Temasys uses Chrome style stats
10+
**/
11+
exports.getStats = function(pc, opts, callback) {
12+
if (pc.iceConnectionState !== 'connected') return callback();
13+
return google.getStats.apply(null, arguments);
14+
};
15+
16+
/**
17+
Check if Temasys is handling this connection
18+
**/
19+
exports.check = function() {
20+
return document &&
21+
document.body &&
22+
document.body.querySelectorAll &&
23+
document.body.querySelectorAll('[type="application/x-temwebrtcplugin"]').length > 0;
24+
};

lib/providers/unsupported.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
Unsupported provider
3+
**/
4+
exports.id = 'unsupported';
5+
6+
/**
7+
Implementation for Mozilla RTCPeerConnection stats
8+
**/
9+
exports.getStats = function(pc, opts, callback) {
10+
return callback(null, []);
11+
}
12+
13+
/**
14+
Unsupported supports all
15+
**/
16+
exports.check = function() {
17+
return true;
18+
}

lib/reporter.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function Reporter(opts) {
2828
}
2929

3030
Reporter.prototype.isActive = function() {
31-
if (!this.reports) return false;
31+
if (!this.reports) return false;
3232

3333
var report = this.getReport('candidatePair');
3434
return report && report.activeConnection;
@@ -61,7 +61,7 @@ Reporter.prototype.getReportById = function(reportId) {
6161
}
6262

6363
Reporter.prototype.getReportsByType = function(reportType) {
64-
return ths.getReportsByTypes([reportType]);
64+
return this.getReportsByTypes([reportType]);
6565
}
6666

6767
/**
@@ -86,8 +86,8 @@ Reporter.prototype.getReportsByTypes = function(reportTypes) {
8686
**/
8787
Reporter.prototype.getChannelReports = function() {
8888

89-
var candidatePairs = this.getReportsByType('candidatePair'),
90-
reports = [];
89+
var candidatePairs = this.getReportsByType('candidatePair') || [];
90+
var reports = [];
9191

9292
for (var i = 0; i < candidatePairs.length; i++) {
9393
var cdp = candidatePairs[i],
@@ -114,12 +114,12 @@ Reporter.prototype.toJSON = function(opts) {
114114
compareTo = opts.compareTo;
115115

116116
if (this.reports) {
117-
for (var i = 0; i < this.reports.length; i++) {
117+
for (var i = 0; i < this.reports.length; i++) {
118118
var report = this.reports[i];
119119
if (exclude && exclude.indexOf(report.type) >= 0) continue;
120120

121121
// If supplied, find a matching report to compare against
122-
if (compareTo) {
122+
if (compareTo && compareTo.reports) {
123123
for (var ci = 0; ci < compareTo.reports.length; ci++) {
124124
var check = compareTo.reports[ci];
125125
if (check.id == report.id) {
@@ -136,15 +136,15 @@ Reporter.prototype.toJSON = function(opts) {
136136
}
137137
}
138138

139-
return {
140-
id: this.id,
141-
connection: this.connection_id,
142-
source: { id: this.source },
143-
target: { id: this.target },
139+
return {
140+
id: this.id,
141+
connection: this.connection_id,
142+
source: { id: this.source },
143+
target: { id: this.target },
144144
mesh: this.room,
145145
status: this.status,
146-
reports: result,
147-
timestamp: now
146+
reports: result,
147+
timestamp: now
148148
};
149149
}
150150

@@ -168,7 +168,7 @@ ChannelReport.prototype.isActive = function() {
168168
**/
169169
ChannelReport.prototype.toJSON = function() {
170170

171-
var result = {
171+
var result = {
172172
id: (this.channel ? this.channel.id : ''),
173173
room: this.room,
174174
active: this.isActive()

0 commit comments

Comments
 (0)