Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add enableDataChannel option to peer #806

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ If `opts` is specified, then the default options (shown below) will be overridde
```
{
initiator: false,
enableDataChannel: true,
channelConfig: {},
channelName: '<random string>',
config: { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }, { urls: 'stun:global.stun.twilio.com:3478?transport=udp' }] },
Expand All @@ -286,6 +287,7 @@ If `opts` is specified, then the default options (shown below) will be overridde
The options do the following:

- `initiator` - set to `true` if this is the initiating peer
- `enableDataChannel` - set to `false` if no data channel should be created for this peer
- `channelConfig` - custom webrtc data channel configuration (used by [`createDataChannel`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createDataChannel))
- `channelName` - custom webrtc data channel name
- `config` - custom webrtc configuration (used by [`RTCPeerConnection`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection) constructor)
Expand Down Expand Up @@ -456,6 +458,7 @@ Possible error codes:
- `ERR_ICE_CONNECTION_FAILURE`
- `ERR_SIGNALING`
- `ERR_DATA_CHANNEL`
- `ERR_DISABLED_DATA_CHANNEL`
- `ERR_CONNECTION_FAILURE`


Expand Down
40 changes: 31 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class Peer extends stream.Duplex {
: null

this.initiator = opts.initiator || false
this.enableDataChannel = opts.enableDataChannel ?? true
this.channelConfig = opts.channelConfig || Peer.channelConfig
this.channelNegotiated = this.channelConfig.negotiated
this.config = Object.assign({}, Peer.config, opts.config)
Expand Down Expand Up @@ -137,13 +138,15 @@ class Peer extends stream.Duplex {
// - onfingerprintfailure
// - onnegotiationneeded

if (this.initiator || this.channelNegotiated) {
this._setupData({
channel: this._pc.createDataChannel(this.channelName, this.channelConfig)
})
} else {
this._pc.ondatachannel = event => {
this._setupData(event)
if (this.enableDataChannel) {
if (this.initiator || this.channelNegotiated) {
this._setupData({
channel: this._pc.createDataChannel(this.channelName, this.channelConfig)
})
} else {
this._pc.ondatachannel = event => {
this._setupData(event)
}
}
}

Expand Down Expand Up @@ -172,7 +175,7 @@ class Peer extends stream.Duplex {
// HACK: it's possible channel.readyState is "closing" before peer.destroy() fires
// https://bugs.chromium.org/p/chromium/issues/detail?id=882743
get connected () {
return (this._connected && this._channel.readyState === 'open')
return (this._connected && (this.enableDataChannel ? this._channel && this._channel.readyState === 'open' : true));
}

address () {
Expand Down Expand Up @@ -244,6 +247,7 @@ class Peer extends stream.Duplex {
* @param {ArrayBufferView|ArrayBuffer|Buffer|string|Blob} chunk
*/
send (chunk) {
if (!this.enableDataChannel) throw errCode(new Error('Cannot write if data channel is disabled'), 'ERR_DISABLED_DATA_CHANNEL')
if (this.destroying) return
if (this.destroyed) throw errCode(new Error('cannot send after peer is destroyed'), 'ERR_DESTROYED')
this._channel.send(chunk)
Expand Down Expand Up @@ -500,6 +504,12 @@ class Peer extends stream.Duplex {
}

_setupData (event) {
if(!this.enableDataChannel)
{
// Configured to NOT use a data channel, calling setupData is invalid in this case.
return this.destroy(errCode(new Error('Tried to create data channel despite disabled data channel.'), 'ERR_DISABLED_DATA_CHANNEL'))
}

if (!event.channel) {
// In some situations `pc.createDataChannel()` returns `undefined` (in wrtc),
// which is invalid behavior. Handle it gracefully.
Expand Down Expand Up @@ -548,11 +558,23 @@ class Peer extends stream.Duplex {
}, CHANNEL_CLOSING_TIMEOUT)
}

_read () {}
_read () {
if(!this.enableDataChannel)
{
// Calling read without data channel is invalid, throw error.
throw errCode(new Error('Cannot read with data channel not enabled.'), 'ERR_DISABLED_DATA_CHANNEL')
}
}

_write (chunk, encoding, cb) {
if (this.destroyed) return cb(errCode(new Error('cannot write after peer is destroyed'), 'ERR_DATA_CHANNEL'))

if(!this.enableDataChannel)
{
// Calling write without data channel is invalid, throw error.
return cb(errCode(new Error('Cannot write with data channel not enabled.'), 'ERR_DISABLED_DATA_CHANNEL'))
}

if (this._connected) {
try {
this.send(chunk)
Expand Down
2 changes: 1 addition & 1 deletion simplepeer.min.js

Large diffs are not rendered by default.

31 changes: 31 additions & 0 deletions test/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,34 @@ test('ensure iceStateChange fires when connection failed', (t) => {
peer.destroy()
peer._pc.oniceconnectionstatechange()
})

test('ensure enableDataChannel is being respected', async (t) => {
t.plan(4)
const peer = new Peer({ config, initiator: true, wrtc: common.wrtc, enableDataChannel: false })

const onSignalPromise = new Promise((resolve,reject) => {
peer.on('signal', data => {
resolve(data);
});
});

t.throws(function(){peer.send("data")},"Sending data is not allowed with enableDataChannel set to false");
t.throws(function(){peer.write("data")},"Writing data is not allowed with enableDataChannel set to false");
t.throws(function(){peer.read()},"Reading data is not allowed with enableDataChannel set to false");

const data = await onSignalPromise;
const lines = data.sdp.split("\r\n");

// Determining whether we have found any media descriptions in SDP offer
// Since no data channel, or audio/video channel is being created, we shouldn't find any
let mLines = [];
lines.forEach(line => {
if(line.substring = "m=")
{
mLines.concat(line)
}
});
t.assert(mLines.length === 0, "No media descriptions have been created");

t.end();
})