-
Notifications
You must be signed in to change notification settings - Fork 847
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #549 from webrtc/unRevert
Revert "Revert "Merge pull request #527 from fippo/rtcicecandidate""
- Loading branch information
Showing
6 changed files
with
278 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/* | ||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | ||
* | ||
* Use of this source code is governed by a BSD-style license | ||
* that can be found in the LICENSE file in the root of the source | ||
* tree. | ||
*/ | ||
/* eslint-env node */ | ||
'use strict'; | ||
|
||
var SDPUtils = require('sdp'); | ||
|
||
// Wraps the peerconnection event eventNameToWrap in a function | ||
// which returns the modified event object. | ||
function wrapPeerConnectionEvent(eventNameToWrap, wrapper) { | ||
if (!window.RTCPeerConnection) { | ||
return; | ||
} | ||
var proto = window.RTCPeerConnection.prototype; | ||
var nativeAddEventListener = proto.addEventListener; | ||
proto.addEventListener = function(nativeEventName, cb) { | ||
if (nativeEventName !== eventNameToWrap) { | ||
return nativeAddEventListener.apply(this, arguments); | ||
} | ||
var wrappedCallback = function(e) { | ||
cb(wrapper(e)); | ||
}; | ||
this._eventMap = this._eventMap || {}; | ||
this._eventMap[cb] = wrappedCallback; | ||
return nativeAddEventListener.apply(this, [nativeEventName, | ||
wrappedCallback]); | ||
}; | ||
|
||
var nativeRemoveEventListener = proto.removeEventListener; | ||
proto.removeEventListener = function(nativeEventName, cb) { | ||
if (nativeEventName !== eventNameToWrap || !this._eventMap | ||
|| !this._eventMap[cb]) { | ||
return nativeRemoveEventListener.apply(this, arguments); | ||
} | ||
var unwrappedCb = this._eventMap[cb]; | ||
delete this._eventMap[cb]; | ||
return nativeRemoveEventListener.apply(this, [nativeEventName, | ||
unwrappedCb]); | ||
}; | ||
|
||
Object.defineProperty(proto, 'on' + eventNameToWrap, { | ||
get: function() { | ||
return this['_on' + eventNameToWrap]; | ||
}, | ||
set: function(cb) { | ||
if (this['_on' + eventNameToWrap]) { | ||
this.removeEventListener(eventNameToWrap, | ||
this['_on' + eventNameToWrap]); | ||
} | ||
this.addEventListener(eventNameToWrap, | ||
this['_on' + eventNameToWrap] = cb); | ||
} | ||
}); | ||
} | ||
|
||
module.exports = { | ||
shimRTCIceCandidate: function() { | ||
// foundation is arbitrarily chosen as an indicator for full support for | ||
// https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface | ||
if (window.RTCIceCandidate && 'foundation' in | ||
window.RTCIceCandidate.prototype) { | ||
return; | ||
} | ||
|
||
var NativeRTCIceCandidate = window.RTCIceCandidate; | ||
window.RTCIceCandidate = function(args) { | ||
// Remove the a= which shouldn't be part of the candidate string. | ||
if (typeof args === 'object' && args.candidate && | ||
args.candidate.indexOf('a=') === 0) { | ||
args = JSON.parse(JSON.stringify(args)); | ||
args.candidate = args.candidate.substr(2); | ||
} | ||
|
||
// Augment the native candidate with the parsed fields. | ||
var nativeCandidate = new NativeRTCIceCandidate(args); | ||
var parsedCandidate = SDPUtils.parseCandidate(args.candidate); | ||
var augmentedCandidate = Object.assign(nativeCandidate, | ||
parsedCandidate); | ||
|
||
// Add a serializer that does not serialize the extra attributes. | ||
augmentedCandidate.toJSON = function() { | ||
return { | ||
candidate: augmentedCandidate.candidate, | ||
sdpMid: augmentedCandidate.sdpMid, | ||
sdpMLineIndex: augmentedCandidate.sdpMLineIndex, | ||
ufrag: augmentedCandidate.ufrag | ||
}; | ||
}; | ||
return augmentedCandidate; | ||
}; | ||
|
||
// Hook up the augmented candidate in onicecandidate and | ||
// addEventListener('icecandidate', ...) | ||
wrapPeerConnectionEvent('icecandidate', function(e) { | ||
if (e.candidate) { | ||
Object.defineProperty(e, 'candidate', { | ||
value: new RTCIceCandidate(e.candidate), writable: 'false' | ||
}); | ||
} | ||
return e; | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | ||
* | ||
* Use of this source code is governed by a BSD-style license | ||
* that can be found in the LICENSE file in the root of the source | ||
* tree. | ||
*/ | ||
/* eslint-env node */ | ||
const chai = require('chai'); | ||
const expect = chai.expect; | ||
|
||
describe('RTCIceCandidate', () => { | ||
const shim = require('../../src/js/common'); | ||
beforeEach(() => { | ||
global.window = global; | ||
window.RTCIceCandidate = function(args) { | ||
return args; | ||
}; | ||
window.RTCPeerConnection = function() {}; | ||
shim.shimRTCIceCandidate(); | ||
}); | ||
|
||
const candidateString = 'candidate:702786350 2 udp 41819902 8.8.8.8 60769 ' + | ||
'typ relay raddr 8.8.8.8 rport 1234 ' + | ||
'tcptype active ' + | ||
'ufrag abc'; | ||
|
||
describe('constructor', () => { | ||
it('retains the candidate', () => { | ||
const candidate = new RTCIceCandidate({ | ||
candidate: candidateString, | ||
sdpMid: 'audio', | ||
sdpMLineIndex: 0 | ||
}); | ||
expect(candidate.candidate).to.equal(candidateString); | ||
expect(candidate.sdpMid).to.equal('audio'); | ||
expect(candidate.sdpMLineIndex).to.equal(0); | ||
}); | ||
|
||
it('drops the a= part of the candidate if present', () => { | ||
const candidate = new RTCIceCandidate({ | ||
candidate: 'a=' + candidateString, | ||
sdpMid: 'audio', | ||
sdpMLineIndex: 0 | ||
}); | ||
expect(candidate.candidate).to.equal(candidateString); | ||
}); | ||
|
||
it('parses the candidate', () => { | ||
const candidate = new RTCIceCandidate({ | ||
candidate: candidateString, | ||
sdpMid: 'audio', | ||
sdpMLineIndex: 0 | ||
}); | ||
expect(candidate.foundation).to.equal('702786350'); | ||
// expect(candidate.component).to.equal('2'); // TODO | ||
expect(candidate.priority).to.equal(41819902); | ||
expect(candidate.ip).to.equal('8.8.8.8'); | ||
expect(candidate.protocol).to.equal('udp'); | ||
expect(candidate.port).to.equal(60769); | ||
expect(candidate.type).to.equal('relay'); | ||
expect(candidate.tcpType).to.equal('active'); | ||
expect(candidate.relatedAddress).to.equal('8.8.8.8'); | ||
expect(candidate.relatedPort).to.equal(1234); | ||
expect(candidate.ufrag).to.equal('abc'); | ||
}); | ||
}); | ||
|
||
it('does not serialize the extra attributes', () => { | ||
const candidate = new RTCIceCandidate({ | ||
candidate: candidateString, | ||
sdpMid: 'audio', | ||
sdpMLineIndex: 0, | ||
ufrag: 'someufrag' | ||
}); | ||
const serialized = JSON.stringify(candidate); | ||
// there should be only 4 items in the JSON. | ||
expect(Object.keys(JSON.parse(serialized)).length).to.equal(4); | ||
}); | ||
}); |