Socket
Socket
Sign inDemoInstall

rtcpeerconnection

Package Overview
Dependencies
Maintainers
3
Versions
83
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rtcpeerconnection - npm Package Compare versions

Comparing version 1.1.1 to 2.0.0

.jshintignore

29

package.json
{
"name": "rtcpeerconnection",
"version": "1.1.1",
"description": "A tiny browser module that gives normalizes and simplifies the API for WebRTC peer connections.",
"version": "2.0.0",
"description": "A tiny browser module that normalizes and simplifies the API for WebRTC peer connections.",
"main": "rtcpeerconnection.js",

@@ -13,3 +13,4 @@ "repository": {

"RTCPeerConnection",
"WebRTC"
"WebRTC",
"Jingle"
],

@@ -19,11 +20,23 @@ "author": "Henrik Joreteg <henrik@andyet.net>",

"dependencies": {
"wildemitter": "0.0.5",
"webrtcsupport": "0.7.1"
"wildemitter": "1.x",
"webrtcsupport": "0.7.x",
"traceablepeerconnection": "0.1.x",
"sdp-jingle-json": "1.x",
"underscore": "1.x"
},
"devDependencies": {
"browserify": "2.x"
"browserify": "2.x",
"precommit-hook": "0.3.x",
"tape": "2.x"
},
"jshintConfig": {
"expr": true
"testling": {
"files": "test/*.js",
"browsers": [
"ie/10..latest",
"chrome/33..latest",
"firefox/24..latest",
"safari/latest",
"opera/18..latest"
]
}
}

@@ -119,19 +119,28 @@ # RTCPeerConnection

connection.on('offer', function (offer) {
// you can just call answer
pc.answer(offer, function (err, answer) {
if (!err) connection.send('answer', answer);
});
// let the peerconnection handle the offer
// by calling handleOffer
pc.handleOffer(offer, function (err) {
if (err) {
// handle error
return;
}
// you can call answer with contstraints
pc.answer(offer, MY_CONSTRAINTS, function (err, answer) {
if (!err) connection.send('answer', answer);
});
// you can just call answer
pc.answer(function (err, answer) {
if (!err) connection.send('answer', answer);
});
// or you can use one of the shortcuts answers
// you can call answer with contstraints
pc.answer(MY_CONSTRAINTS, function (err, answer) {
if (!err) connection.send('answer', answer);
});
// for video only
pc.answerVideoOnly(offer, function (err, answer) { ... });
// or you can use one of the shortcuts answers
// and audio only
pc.answerAudioOnly(offer, function (err, answer) { ... });
// for video only
pc.answerVideoOnly(function (err, answer) { ... });
// and audio only
pc.answerAudioOnly(function (err, answer) { ... });
});
});

@@ -138,0 +147,0 @@

@@ -0,10 +1,22 @@

var _ = require('underscore');
var util = require('util');
var webrtc = require('webrtcsupport');
var SJJ = require('sdp-jingle-json');
var WildEmitter = require('wildemitter');
var webrtc = require('webrtcsupport');
var peerconn = require('traceablepeerconnection');
function PeerConnection(config, constraints) {
var self = this;
var item;
this.pc = new webrtc.PeerConnection(config, constraints);
WildEmitter.call(this);
config = config || {};
config.iceServers = config.iceServers || [];
this.pc = new peerconn(config, constraints);
// proxy events
this.pc.on('*', function () {
self.emit.apply(self, arguments);
});
// proxy some events directly

@@ -21,6 +33,19 @@ this.pc.onremovestream = this.emit.bind(this, 'removeStream');

// whether to use SDP hack for faster data transfer
this.localDescription = {
contents: []
};
this.remoteDescription = {
contents: []
};
this.localStream = null;
this.remoteStreams = [];
this.config = {
debug: false,
sdpHack: true
ice: {},
sid: '',
isInitiator: true,
sdpSessionID: Date.now(),
useJingle: false
};

@@ -41,8 +66,5 @@

PeerConnection.prototype = Object.create(WildEmitter.prototype, {
constructor: {
value: PeerConnection
}
});
util.inherits(PeerConnection, WildEmitter);
// Add a stream to the peer connection object

@@ -56,4 +78,40 @@ PeerConnection.prototype.addStream = function (stream) {

// Init and add ice candidate object with correct constructor
PeerConnection.prototype.processIce = function (candidate) {
this.pc.addIceCandidate(new webrtc.IceCandidate(candidate));
PeerConnection.prototype.processIce = function (update, cb) {
cb = cb || function () {};
var self = this;
if (update.contents) {
var contentNames = _.pluck(this.remoteDescription.contents, 'name');
var contents = update.contents;
contents.forEach(function (content) {
var transport = content.transport || {};
var candidates = transport.candidates || [];
var mline = contentNames.indexOf(content.name);
var mid = content.name;
candidates.forEach(function (candidate) {
console.log('addicecandidate');
var iceCandidate = SJJ.toCandidateSDP(candidate) + '\r\n';
self.pc.addIceCandidate(new webrtc.IceCandidate({
candidate: iceCandidate,
sdpMLineIndex: mline,
sdpMid: mid
})
/* not yet, breaks Chrome M32 */
/*
, function () {
// well, this success callback is pretty meaningless
},
function (err) {
self.emit('error', err);
}
*/
);
});
});
} else {
self.pc.addIceCandidate(new webrtc.IceCandidate(update.candidate));
}
cb();
};

@@ -71,3 +129,4 @@

};
var callback = hasConstraints ? cb : constraints;
cb = hasConstraints ? cb : constraints;
cb = cb || function () {};

@@ -77,10 +136,40 @@ // Actually generate the offer

function (offer) {
offer.sdp = self._applySdpHack(offer.sdp);
self.pc.setLocalDescription(offer);
self.emit('offer', offer);
if (callback) callback(null, offer);
self.pc.setLocalDescription(offer,
function () {
var jingle;
var expandedOffer = {
type: 'offer',
sdp: offer.sdp
};
if (self.config.useJingle) {
jingle = SJJ.toSessionJSON(offer.sdp, self.config.isInitiator ? 'initiator' : 'responder');
jingle.sid = self.config.sid;
self.localDescription = jingle;
// Save ICE credentials
_.each(jingle.contents, function (content) {
var transport = content.transport || {};
if (transport.ufrag) {
self.config.ice[content.name] = {
ufrag: transport.ufrag,
pwd: transport.pwd
};
}
});
expandedOffer.jingle = jingle;
}
self.emit('offer', expandedOffer);
cb(null, expandedOffer);
},
function (err) {
self.emit('error', err);
cb(err);
}
);
},
function (err) {
self.emit('error', err);
if (callback) callback(err);
cb(err);
},

@@ -91,4 +180,19 @@ mediaConstraints

// Process an incoming offer so that ICE may proceed before deciding
// to answer the request.
PeerConnection.prototype.handleOffer = function (offer, cb) {
cb = cb || function () {};
var self = this;
offer.type = 'offer';
if (offer.jingle) {
offer.sdp = SJJ.toSessionSDP(offer.jingle, self.config.sdpSessionID);
}
self.pc.setRemoteDescription(new webrtc.SessionDescription(offer), function () {
cb();
}, cb);
};
// Answer an offer with audio only
PeerConnection.prototype.answerAudioOnly = function (offer, cb) {
PeerConnection.prototype.answerAudioOnly = function (cb) {
var mediaConstraints = {

@@ -100,7 +204,7 @@ mandatory: {

};
this._answer(offer, mediaConstraints, cb);
this._answer(mediaConstraints, cb);
};
// Answer an offer without offering to recieve
PeerConnection.prototype.answerBroadcastOnly = function (offer, cb) {
PeerConnection.prototype.answerBroadcastOnly = function (cb) {
var mediaConstraints = {

@@ -112,9 +216,9 @@ mandatory: {

};
this._answer(offer, mediaConstraints, cb);
this._answer(mediaConstraints, cb);
};
// Answer an offer with given constraints default is audio/video
PeerConnection.prototype.answer = function (offer, constraints, cb) {
PeerConnection.prototype.answer = function (constraints, cb) {
var self = this;
var hasConstraints = arguments.length === 3;
var hasConstraints = arguments.length === 2;
var callback = hasConstraints ? cb : constraints;

@@ -128,8 +232,20 @@ var mediaConstraints = hasConstraints ? constraints : {

this._answer(offer, mediaConstraints, callback);
this._answer(mediaConstraints, callback);
};
// Process an answer
PeerConnection.prototype.handleAnswer = function (answer) {
this.pc.setRemoteDescription(new webrtc.SessionDescription(answer));
PeerConnection.prototype.handleAnswer = function (answer, cb) {
cb = cb || function () {};
var self = this;
if (answer.jingle) {
answer.sdp = SJJ.toSessionSDP(answer.jingle, self.config.sdpSessionID);
self.remoteDescription = answer.jingle;
}
self.pc.setRemoteDescription(
new webrtc.SessionDescription(answer),
function () {
cb(null);
},
cb
);
};

@@ -144,14 +260,35 @@

// Internal code sharing for various types of answer methods
PeerConnection.prototype._answer = function (offer, constraints, cb) {
PeerConnection.prototype._answer = function (constraints, cb) {
cb = cb || function () {};
var self = this;
this.pc.setRemoteDescription(new webrtc.SessionDescription(offer));
this.pc.createAnswer(
if (!this.pc.remoteDescription) {
// the old API is used, call handleOffer
throw new Error('remoteDescription not set');
}
self.pc.createAnswer(
function (answer) {
answer.sdp = self._applySdpHack(answer.sdp);
self.pc.setLocalDescription(answer);
self.emit('answer', answer);
if (cb) cb(null, answer);
}, function (err) {
self.pc.setLocalDescription(answer,
function () {
var expandedAnswer = {
type: 'answer',
sdp: answer.sdp
};
if (self.config.useJingle) {
var jingle = SJJ.toSessionJSON(answer.sdp);
jingle.sid = self.config.sid;
self.localDescription = jingle;
expandedAnswer.jingle = jingle;
}
self.emit('answer', expandedAnswer);
cb(null, expandedAnswer);
},
function (err) {
self.emit('error', err);
cb(err);
}
);
},
function (err) {
self.emit('error', err);
if (cb) cb(err);
cb(err);
},

@@ -164,4 +301,40 @@ constraints

PeerConnection.prototype._onIce = function (event) {
var self = this;
if (event.candidate) {
this.emit('ice', event.candidate);
var ice = event.candidate;
var expandedCandidate = {
candidate: event.candidate
};
if (self.config.useJingle) {
if (!self.config.ice[ice.sdpMid]) {
var jingle = SJJ.toSessionJSON(self.pc.localDescription.sdp, self.config.isInitiator ? 'initiator' : 'responder');
_.each(jingle.contents, function (content) {
var transport = content.transport || {};
if (transport.ufrag) {
self.config.ice[content.name] = {
ufrag: transport.ufrag,
pwd: transport.pwd
};
}
});
}
expandedCandidate.jingle = {
contents: [{
name: ice.sdpMid,
creator: self.config.isInitiator ? 'initiator' : 'responder',
transport: {
transType: 'iceUdp',
ufrag: self.config.ice[ice.sdpMid].ufrag,
pwd: self.config.ice[ice.sdpMid].pwd,
candidates: [
SJJ.toCandidateJSON(ice.candidate)
]
}
}]
};
}
this.emit('ice', expandedCandidate);
} else {

@@ -180,50 +353,10 @@ this.emit('endOfCandidates');

PeerConnection.prototype._onAddStream = function (event) {
this.remoteStream = event.stream;
this.remoteStreams.push(event.stream);
this.emit('addStream', event);
};
// SDP hack for increasing AS (application specific) data transfer speed allowed in chrome
PeerConnection.prototype._applySdpHack = function (sdp) {
if (!this.config.sdpHack) return sdp;
var parts = sdp.split('b=AS:30');
if (parts.length === 2) {
// increase max data transfer bandwidth to 100 Mbps
return parts[0] + 'b=AS:102400' + parts[1];
} else {
return sdp;
}
};
// Create a data channel spec reference:
// http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCDataChannelInit
PeerConnection.prototype.createDataChannel = function (name, opts) {
opts || (opts = {});
var reliable = !!opts.reliable;
var protocol = opts.protocol || 'text/plain';
var negotiated = !!(opts.negotiated || opts.preset);
var settings;
var channel;
// firefox is a bit more finnicky
if (webrtc.prefix === 'moz') {
if (reliable) {
settings = {
protocol: protocol,
preset: negotiated,
stream: name
};
} else {
settings = {};
}
channel = this.pc.createDataChannel(name, settings);
channel.binaryType = 'blob';
} else {
if (reliable) {
settings = {
reliable: true
};
} else {
settings = {reliable: false};
}
channel = this.pc.createDataChannel(name, settings);
}
var channel = this.pc.createDataChannel(name, opts);
return channel;

@@ -230,0 +363,0 @@ };

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc