Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
78e250a
Add dummy RTCSctpTransport to make the 'maxMessageSize' attribute ava…
lgrahl Oct 26, 2017
dcd48f4
Throw a `TypeError` in case the message is too large for the other pe…
lgrahl Oct 26, 2017
7cd570c
Turn off logging again
lgrahl Oct 26, 2017
4def6d4
Define test cases related to the maximum message size for data channels
lgrahl Oct 28, 2017
f84ce3d
Fix maxMessageSize also depends on the local maximum message size
lgrahl Oct 28, 2017
5d8cec2
Fix handle maxMessageSize 0 case properly (again)
lgrahl Oct 28, 2017
4dd2784
Fix broken maxMessageSize tests
lgrahl Oct 28, 2017
22a2918
Fix apply TypeError shim when sending on data channels to FF >= 57 as…
lgrahl Oct 28, 2017
e78bcce
Replace regular expression with SDPUtils.matchPrefix where useful
lgrahl Oct 28, 2017
d268eed
Fix regression introduced by using SDPUtils.matchPrefix in `getMaxMes…
lgrahl Oct 28, 2017
7de1187
Fix throw DOMException of type TypeError instead of throwing a TypeEr…
lgrahl Oct 31, 2017
9c29712
Fix determine maximum message size correctly (do not rely on the loca…
lgrahl Nov 3, 2017
d6cf288
Fix also apply the 'TypeError on send' shim to FF >= 57 for consisten…
lgrahl Nov 3, 2017
8bfca85
Fix expect tests to pass that were accidentally changed to expect to …
lgrahl Nov 9, 2017
c5c683b
Rename `getFirefoxVersion` to `getRemoteFirefoxVersion`
lgrahl Nov 9, 2017
0711e9d
Replace regex with SDPUtils for checking whether SCTP is being negoti…
lgrahl Nov 9, 2017
64600a6
Reference Chrome data channel send issue (cannot reliably send more t…
lgrahl Nov 9, 2017
5604ef3
Set maxMessageSize to positive infinity in case both peers can handle…
lgrahl Dec 8, 2017
dac3ecf
Fix default remote maximum message size (65535 -> 65536)
lgrahl Dec 16, 2017
ded8522
Add test cases for the expected and negotiated maximum message size i…
lgrahl Dec 21, 2017
9aa3d15
Re-enable the send shim for Firefox >= 57
lgrahl Dec 22, 2017
6aea672
Update e2e test expectations
lgrahl Dec 22, 2017
359e6df
Add workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
lgrahl Dec 23, 2017
2d69512
Merge branch 'master' into dc-max-message-size
alvestrand Jan 12, 2018
d96f5cc
Merge branch 'master' into dc-max-message-size
alvestrand Jan 12, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions src/js/adapter_factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ module.exports = function(dependencies, opts) {
var logging = utils.log;
var browserDetails = utils.detectBrowser(window);

// Export to the adapter global object visible in the browser.
var adapter = {
browserDetails: browserDetails,
extractVersion: utils.extractVersion,
disableLog: utils.disableLog,
disableWarnings: utils.disableWarnings
};

// Uncomment the line below if you want logging to occur, including logging
// for the switch statement below. Can also be turned on in the browser via
// adapter.disableLog(false), but then logging from the switch statement below
Expand All @@ -52,6 +44,15 @@ module.exports = function(dependencies, opts) {
var safariShim = require('./safari/safari_shim') || null;
var commonShim = require('./common_shim') || null;

// Export to the adapter global object visible in the browser.
var adapter = {
browserDetails: browserDetails,
commonShim: commonShim,
extractVersion: utils.extractVersion,
disableLog: utils.disableLog,
disableWarnings: utils.disableWarnings
};

// Shim browser if found.
switch (browserDetails.browser) {
case 'chrome':
Expand All @@ -74,6 +75,8 @@ module.exports = function(dependencies, opts) {
chromeShim.shimGetSendersWithDtmf(window);

commonShim.shimRTCIceCandidate(window);
commonShim.shimMaxMessageSize(window);
commonShim.shimSendThrowTypeError(window);
break;
case 'firefox':
if (!firefoxShim || !firefoxShim.shimPeerConnection ||
Expand All @@ -93,6 +96,8 @@ module.exports = function(dependencies, opts) {
firefoxShim.shimRemoveStream(window);

commonShim.shimRTCIceCandidate(window);
commonShim.shimMaxMessageSize(window);
commonShim.shimSendThrowTypeError(window);
break;
case 'edge':
if (!edgeShim || !edgeShim.shimPeerConnection || !options.shimEdge) {
Expand All @@ -109,6 +114,9 @@ module.exports = function(dependencies, opts) {
edgeShim.shimReplaceTrack(window);

// the edge shim implements the full RTCIceCandidate object.

commonShim.shimMaxMessageSize(window);
commonShim.shimSendThrowTypeError(window);
break;
case 'safari':
if (!safariShim || !options.shimSafari) {
Expand All @@ -129,6 +137,8 @@ module.exports = function(dependencies, opts) {
safariShim.shimCreateOfferLegacy(window);

commonShim.shimRTCIceCandidate(window);
commonShim.shimMaxMessageSize(window);
commonShim.shimSendThrowTypeError(window);
break;
default:
logging('Unsupported browser!');
Expand Down
159 changes: 159 additions & 0 deletions src/js/common_shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,164 @@ module.exports = {
}
return nativeSetAttribute.apply(this, arguments);
};
},

shimMaxMessageSize: function(window) {
if (window.RTCSctpTransport) {
return;
}
var browserDetails = utils.detectBrowser(window);

if (!('sctp' in window.RTCPeerConnection.prototype)) {
Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {
get: function() {
return typeof this._sctp === 'undefined' ? null : this._sctp;
}
});
}

var sctpInDescription = function(description) {
var sections = SDPUtils.splitSections(description.sdp);
sections.shift();
return sections.some(function(mediaSection) {
var mLine = SDPUtils.parseMLine(mediaSection);
return mLine && mLine.kind === 'application'
&& mLine.protocol.indexOf('SCTP') !== -1;
});
};

var getRemoteFirefoxVersion = function(description) {
// TODO: Is there a better solution for detecting Firefox?
var match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);
if (match === null || match.length < 2) {
return -1;
}
var version = parseInt(match[1], 10);
// Test for NaN (yes, this is ugly)
return version !== version ? -1 : version;
};

var getCanSendMaxMessageSize = function(remoteIsFirefox) {
// Every implementation we know can send at least 64 KiB.
// Note: Although Chrome is technically able to send up to 256 KiB, the
// data does not reach the other peer reliably.
// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419
var canSendMaxMessageSize = 65536;
if (browserDetails.browser === 'firefox') {
if (browserDetails.version < 57) {
if (remoteIsFirefox === -1) {
// FF < 57 will send in 16 KiB chunks using the deprecated PPID
// fragmentation.
canSendMaxMessageSize = 16384;
} else {
// However, other FF (and RAWRTC) can reassemble PPID-fragmented
// messages. Thus, supporting ~2 GiB when sending.
canSendMaxMessageSize = 2147483637;
}
} else {
// Currently, all FF >= 57 will reset the remote maximum message size
// to the default value when a data channel is created at a later
// stage. :(
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
canSendMaxMessageSize =
browserDetails.version === 57 ? 65535 : 65536;
}
}
return canSendMaxMessageSize;
};

var getMaxMessageSize = function(description, remoteIsFirefox) {
// Note: 65536 bytes is the default value from the SDP spec. Also,
// every implementation we know supports receiving 65536 bytes.
var maxMessageSize = 65536;

// FF 57 has a slightly incorrect default remote max message size, so
// we need to adjust it here to avoid a failure when sending.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697
if (browserDetails.browser === 'firefox'
&& browserDetails.version === 57) {
maxMessageSize = 65535;
}

var match = SDPUtils.matchPrefix(description.sdp, 'a=max-message-size:');
if (match.length > 0) {
maxMessageSize = parseInt(match[0].substr(19), 10);
} else if (browserDetails.browser === 'firefox' &&
remoteIsFirefox !== -1) {
// If the maximum message size is not present in the remote SDP and
// both local and remote are Firefox, the remote peer can receive
// ~2 GiB.
maxMessageSize = 2147483637;
}
return maxMessageSize;
};

var origSetRemoteDescription =
window.RTCPeerConnection.prototype.setRemoteDescription;
window.RTCPeerConnection.prototype.setRemoteDescription = function() {
var pc = this;
pc._sctp = null;

if (sctpInDescription(arguments[0])) {
// Check if the remote is FF.
var isFirefox = getRemoteFirefoxVersion(arguments[0]);

// Get the maximum message size the local peer is capable of sending
var canSendMMS = getCanSendMaxMessageSize(isFirefox);

// Get the maximum message size of the remote peer.
var remoteMMS = getMaxMessageSize(arguments[0], isFirefox);

// Determine final maximum message size
var maxMessageSize;
if (canSendMMS === 0 && remoteMMS === 0) {
maxMessageSize = Number.POSITIVE_INFINITY;
} else if (canSendMMS === 0 || remoteMMS === 0) {
maxMessageSize = Math.max(canSendMMS, remoteMMS);
} else {
maxMessageSize = Math.min(canSendMMS, remoteMMS);
}

// Create a dummy RTCSctpTransport object and the 'maxMessageSize'
// attribute.
var sctp = {};
Object.defineProperty(sctp, 'maxMessageSize', {
get: function() {
return maxMessageSize;
}
});
pc._sctp = sctp;
}

return origSetRemoteDescription.apply(pc, arguments);
};
},

shimSendThrowTypeError: function(window) {
// Note: Although Firefox >= 57 has a native implementation, the maximum
// message size can be reset for all data channels at a later stage.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831

var origCreateDataChannel =
window.RTCPeerConnection.prototype.createDataChannel;
window.RTCPeerConnection.prototype.createDataChannel = function() {
var pc = this;
var dataChannel = origCreateDataChannel.apply(pc, arguments);
var origDataChannelSend = dataChannel.send;

// Patch 'send' method
dataChannel.send = function() {
var dc = this;
var data = arguments[0];
var length = data.length || data.size || data.byteLength;
if (length > pc.sctp.maxMessageSize) {
throw new DOMException('Message too large (can send a maximum of ' +
pc.sctp.maxMessageSize + ' bytes)', 'TypeError');
}
return origDataChannelSend.apply(dc, arguments);
};

return dataChannel;
};
}
};
14 changes: 14 additions & 0 deletions test/e2e/expectations/chrome-beta
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ PASS getStats returns a Promise
PASS getStats resolves the Promise with a Map(like)
PASS getUserMedia navigator.getUserMedia exists
PASS getUserMedia navigator.getUserMedia calls the callback
PASS maxMessageSize sctp attribute exists
PASS maxMessageSize sctp attribute is null before offer/answer
PASS maxMessageSize sctp attribute is null if SCTP not negotiated
PASS maxMessageSize sctp and maxMessageSize set if SCTP negotiated
PASS maxMessageSize send largest possible single message
PASS maxMessageSize throws an exception if the message is too large
PASS maxMessageSize throws an exception if the message is too large (using a secondary data channel)
PASS maxMessageSize is as expected for chrome>=0 and chrome>=0 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and firefox<=56 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and firefox>=57 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 64 KiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 1.5 GiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 2 GiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and Unlimited -> 65536
PASS navigator.mediaDevices exists
PASS navigator.mediaDevices is an EventTarget
PASS navigator.mediaDevices implements the devicechange event
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/expectations/chrome-beta-no-experimental
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ PASS getStats returns a Promise
PASS getStats resolves the Promise with a Map(like)
PASS getUserMedia navigator.getUserMedia exists
PASS getUserMedia navigator.getUserMedia calls the callback
PASS maxMessageSize sctp attribute exists
PASS maxMessageSize sctp attribute is null before offer/answer
PASS maxMessageSize sctp attribute is null if SCTP not negotiated
PASS maxMessageSize sctp and maxMessageSize set if SCTP negotiated
PASS maxMessageSize send largest possible single message
PASS maxMessageSize throws an exception if the message is too large
PASS maxMessageSize throws an exception if the message is too large (using a secondary data channel)
PASS maxMessageSize is as expected for chrome>=0 and chrome>=0 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and firefox<=56 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and firefox>=57 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 64 KiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 1.5 GiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 2 GiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and Unlimited -> 65536
PASS navigator.mediaDevices exists
PASS navigator.mediaDevices is an EventTarget
PASS navigator.mediaDevices implements the devicechange event
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/expectations/chrome-stable
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ PASS getStats returns a Promise
PASS getStats resolves the Promise with a Map(like)
PASS getUserMedia navigator.getUserMedia exists
PASS getUserMedia navigator.getUserMedia calls the callback
PASS maxMessageSize sctp attribute exists
PASS maxMessageSize sctp attribute is null before offer/answer
PASS maxMessageSize sctp attribute is null if SCTP not negotiated
PASS maxMessageSize sctp and maxMessageSize set if SCTP negotiated
PASS maxMessageSize send largest possible single message
PASS maxMessageSize throws an exception if the message is too large
PASS maxMessageSize throws an exception if the message is too large (using a secondary data channel)
PASS maxMessageSize is as expected for chrome>=0 and chrome>=0 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and firefox<=56 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and firefox>=57 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 64 KiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 1.5 GiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 2 GiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and Unlimited -> 65536
PASS navigator.mediaDevices exists
PASS navigator.mediaDevices is an EventTarget
PASS navigator.mediaDevices implements the devicechange event
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/expectations/chrome-stable-no-experimental
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ PASS getStats returns a Promise
PASS getStats resolves the Promise with a Map(like)
PASS getUserMedia navigator.getUserMedia exists
PASS getUserMedia navigator.getUserMedia calls the callback
PASS maxMessageSize sctp attribute exists
PASS maxMessageSize sctp attribute is null before offer/answer
PASS maxMessageSize sctp attribute is null if SCTP not negotiated
PASS maxMessageSize sctp and maxMessageSize set if SCTP negotiated
PASS maxMessageSize send largest possible single message
PASS maxMessageSize throws an exception if the message is too large
PASS maxMessageSize throws an exception if the message is too large (using a secondary data channel)
PASS maxMessageSize is as expected for chrome>=0 and chrome>=0 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and firefox<=56 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and firefox>=57 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 64 KiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 1.5 GiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 2 GiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and Unlimited -> 65536
PASS navigator.mediaDevices exists
PASS navigator.mediaDevices is an EventTarget
PASS navigator.mediaDevices implements the devicechange event
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/expectations/chrome-unstable
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ PASS getStats returns a Promise
PASS getStats resolves the Promise with a Map(like)
PASS getUserMedia navigator.getUserMedia exists
PASS getUserMedia navigator.getUserMedia calls the callback
PASS maxMessageSize sctp attribute exists
PASS maxMessageSize sctp attribute is null before offer/answer
PASS maxMessageSize sctp attribute is null if SCTP not negotiated
PASS maxMessageSize sctp and maxMessageSize set if SCTP negotiated
PASS maxMessageSize send largest possible single message
PASS maxMessageSize throws an exception if the message is too large
PASS maxMessageSize throws an exception if the message is too large (using a secondary data channel)
PASS maxMessageSize is as expected for chrome>=0 and chrome>=0 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and firefox<=56 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and firefox>=57 -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 64 KiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 1.5 GiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and 2 GiB -> 65536
PASS maxMessageSize is as expected for chrome>=0 and Unlimited -> 65536
PASS navigator.mediaDevices exists
PASS navigator.mediaDevices is an EventTarget
PASS navigator.mediaDevices implements the devicechange event
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/expectations/firefox-beta
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ PASS getStats returns a Promise
PASS getStats resolves the Promise with a Map(like)
PASS getUserMedia navigator.getUserMedia exists
PASS getUserMedia navigator.getUserMedia calls the callback
PASS maxMessageSize sctp attribute exists
PASS maxMessageSize sctp attribute is null before offer/answer
PASS maxMessageSize sctp attribute is null if SCTP not negotiated
PASS maxMessageSize sctp and maxMessageSize set if SCTP negotiated
PASS maxMessageSize send largest possible single message
PASS maxMessageSize throws an exception if the message is too large
PASS maxMessageSize throws an exception if the message is too large (using a secondary data channel)
PASS maxMessageSize is as expected for firefox>=58 and chrome>=0 -> 65536
PASS maxMessageSize is as expected for firefox>=58 and firefox<=56 -> 65536
PASS maxMessageSize is as expected for firefox>=58 and firefox>=57 -> 65536
PASS maxMessageSize is as expected for firefox>=58 and 64 KiB -> 65536
PASS maxMessageSize is as expected for firefox>=58 and 1.5 GiB -> 65536
PASS maxMessageSize is as expected for firefox>=58 and 2 GiB -> 65536
PASS maxMessageSize is as expected for firefox>=58 and Unlimited -> 65536
PASS navigator.mediaDevices exists
PASS navigator.mediaDevices is an EventTarget
PASS navigator.mediaDevices implements the devicechange event
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/expectations/firefox-esr
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ PASS getStats returns a Promise
PASS getStats resolves the Promise with a Map(like)
PASS getUserMedia navigator.getUserMedia exists
PASS getUserMedia navigator.getUserMedia calls the callback
PASS maxMessageSize sctp attribute exists
PASS maxMessageSize sctp attribute is null before offer/answer
PASS maxMessageSize sctp attribute is null if SCTP not negotiated
PASS maxMessageSize sctp and maxMessageSize set if SCTP negotiated
PASS maxMessageSize send largest possible single message
PASS maxMessageSize throws an exception if the message is too large
PASS maxMessageSize throws an exception if the message is too large (using a secondary data channel)
PASS maxMessageSize is as expected for firefox<=56 and chrome>=0 -> 16384
PASS maxMessageSize is as expected for firefox<=56 and firefox<=56 -> 2147483637
PASS maxMessageSize is as expected for firefox<=56 and firefox>=57 -> 1073741823
PASS maxMessageSize is as expected for firefox<=56 and 64 KiB -> 16384
PASS maxMessageSize is as expected for firefox<=56 and 1.5 GiB -> 16384
PASS maxMessageSize is as expected for firefox<=56 and 2 GiB -> 16384
PASS maxMessageSize is as expected for firefox<=56 and Unlimited -> 16384
PASS navigator.mediaDevices exists
PASS navigator.mediaDevices is an EventTarget
PASS navigator.mediaDevices implements the devicechange event
Expand Down
Loading