You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TraceablePeerConnection.js 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. function TraceablePeerConnection(ice_config, constraints) {
  2. var self = this;
  3. var RTCPeerconnection = navigator.mozGetUserMedia ? mozRTCPeerConnection : webkitRTCPeerConnection;
  4. this.peerconnection = new RTCPeerconnection(ice_config, constraints);
  5. this.updateLog = [];
  6. this.stats = {};
  7. this.statsinterval = null;
  8. this.maxstats = 0; // limit to 300 values, i.e. 5 minutes; set to 0 to disable
  9. // override as desired
  10. this.trace = function (what, info) {
  11. //console.warn('WTRACE', what, info);
  12. self.updateLog.push({
  13. time: new Date(),
  14. type: what,
  15. value: info || ""
  16. });
  17. };
  18. this.onicecandidate = null;
  19. this.peerconnection.onicecandidate = function (event) {
  20. self.trace('onicecandidate', JSON.stringify(event.candidate, null, ' '));
  21. if (self.onicecandidate !== null) {
  22. self.onicecandidate(event);
  23. }
  24. };
  25. this.onaddstream = null;
  26. this.peerconnection.onaddstream = function (event) {
  27. self.trace('onaddstream', event.stream.id);
  28. if (self.onaddstream !== null) {
  29. self.onaddstream(event);
  30. }
  31. };
  32. this.onremovestream = null;
  33. this.peerconnection.onremovestream = function (event) {
  34. self.trace('onremovestream', event.stream.id);
  35. if (self.onremovestream !== null) {
  36. self.onremovestream(event);
  37. }
  38. };
  39. this.onsignalingstatechange = null;
  40. this.peerconnection.onsignalingstatechange = function (event) {
  41. self.trace('onsignalingstatechange', self.signalingState);
  42. if (self.onsignalingstatechange !== null) {
  43. self.onsignalingstatechange(event);
  44. }
  45. };
  46. this.oniceconnectionstatechange = null;
  47. this.peerconnection.oniceconnectionstatechange = function (event) {
  48. self.trace('oniceconnectionstatechange', self.iceConnectionState);
  49. if (self.oniceconnectionstatechange !== null) {
  50. self.oniceconnectionstatechange(event);
  51. }
  52. };
  53. this.onnegotiationneeded = null;
  54. this.peerconnection.onnegotiationneeded = function (event) {
  55. self.trace('onnegotiationneeded');
  56. if (self.onnegotiationneeded !== null) {
  57. self.onnegotiationneeded(event);
  58. }
  59. };
  60. self.ondatachannel = null;
  61. this.peerconnection.ondatachannel = function (event) {
  62. self.trace('ondatachannel', event);
  63. if (self.ondatachannel !== null) {
  64. self.ondatachannel(event);
  65. }
  66. };
  67. if (!navigator.mozGetUserMedia && this.maxstats) {
  68. this.statsinterval = window.setInterval(function() {
  69. self.peerconnection.getStats(function(stats) {
  70. var results = stats.result();
  71. for (var i = 0; i < results.length; ++i) {
  72. //console.log(results[i].type, results[i].id, results[i].names())
  73. var now = new Date();
  74. results[i].names().forEach(function (name) {
  75. var id = results[i].id + '-' + name;
  76. if (!self.stats[id]) {
  77. self.stats[id] = {
  78. startTime: now,
  79. endTime: now,
  80. values: [],
  81. times: []
  82. };
  83. }
  84. self.stats[id].values.push(results[i].stat(name));
  85. self.stats[id].times.push(now.getTime());
  86. if (self.stats[id].values.length > self.maxstats) {
  87. self.stats[id].values.shift();
  88. self.stats[id].times.shift();
  89. }
  90. self.stats[id].endTime = now;
  91. });
  92. }
  93. });
  94. }, 1000);
  95. }
  96. };
  97. dumpSDP = function(description) {
  98. return 'type: ' + description.type + '\r\n' + description.sdp;
  99. }
  100. if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) {
  101. TraceablePeerConnection.prototype.__defineGetter__('signalingState', function() { return this.peerconnection.signalingState; });
  102. TraceablePeerConnection.prototype.__defineGetter__('iceConnectionState', function() { return this.peerconnection.iceConnectionState; });
  103. TraceablePeerConnection.prototype.__defineGetter__('localDescription', function() {
  104. var publicLocalDescription = APP.simulcast.reverseTransformLocalDescription(this.peerconnection.localDescription);
  105. return publicLocalDescription;
  106. });
  107. TraceablePeerConnection.prototype.__defineGetter__('remoteDescription', function() {
  108. var publicRemoteDescription = APP.simulcast.reverseTransformRemoteDescription(this.peerconnection.remoteDescription);
  109. return publicRemoteDescription;
  110. });
  111. }
  112. TraceablePeerConnection.prototype.addStream = function (stream) {
  113. this.trace('addStream', stream.id);
  114. APP.simulcast.resetSender();
  115. try
  116. {
  117. this.peerconnection.addStream(stream);
  118. }
  119. catch (e)
  120. {
  121. console.error(e);
  122. return;
  123. }
  124. };
  125. TraceablePeerConnection.prototype.removeStream = function (stream, stopStreams) {
  126. this.trace('removeStream', stream.id);
  127. APP.simulcast.resetSender();
  128. if(stopStreams) {
  129. stream.getAudioTracks().forEach(function (track) {
  130. track.stop();
  131. });
  132. stream.getVideoTracks().forEach(function (track) {
  133. track.stop();
  134. });
  135. }
  136. this.peerconnection.removeStream(stream);
  137. };
  138. TraceablePeerConnection.prototype.createDataChannel = function (label, opts) {
  139. this.trace('createDataChannel', label, opts);
  140. return this.peerconnection.createDataChannel(label, opts);
  141. };
  142. TraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) {
  143. var self = this;
  144. description = APP.simulcast.transformLocalDescription(description);
  145. this.trace('setLocalDescription', dumpSDP(description));
  146. this.peerconnection.setLocalDescription(description,
  147. function () {
  148. self.trace('setLocalDescriptionOnSuccess');
  149. successCallback();
  150. },
  151. function (err) {
  152. self.trace('setLocalDescriptionOnFailure', err);
  153. failureCallback(err);
  154. }
  155. );
  156. /*
  157. if (this.statsinterval === null && this.maxstats > 0) {
  158. // start gathering stats
  159. }
  160. */
  161. };
  162. TraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) {
  163. var self = this;
  164. description = APP.simulcast.transformRemoteDescription(description);
  165. this.trace('setRemoteDescription', dumpSDP(description));
  166. this.peerconnection.setRemoteDescription(description,
  167. function () {
  168. self.trace('setRemoteDescriptionOnSuccess');
  169. successCallback();
  170. },
  171. function (err) {
  172. self.trace('setRemoteDescriptionOnFailure', err);
  173. failureCallback(err);
  174. }
  175. );
  176. /*
  177. if (this.statsinterval === null && this.maxstats > 0) {
  178. // start gathering stats
  179. }
  180. */
  181. };
  182. TraceablePeerConnection.prototype.close = function () {
  183. this.trace('stop');
  184. if (this.statsinterval !== null) {
  185. window.clearInterval(this.statsinterval);
  186. this.statsinterval = null;
  187. }
  188. this.peerconnection.close();
  189. };
  190. TraceablePeerConnection.prototype.createOffer = function (successCallback, failureCallback, constraints) {
  191. var self = this;
  192. this.trace('createOffer', JSON.stringify(constraints, null, ' '));
  193. this.peerconnection.createOffer(
  194. function (offer) {
  195. self.trace('createOfferOnSuccess', dumpSDP(offer));
  196. successCallback(offer);
  197. },
  198. function(err) {
  199. self.trace('createOfferOnFailure', err);
  200. failureCallback(err);
  201. },
  202. constraints
  203. );
  204. };
  205. TraceablePeerConnection.prototype.createAnswer = function (successCallback, failureCallback, constraints) {
  206. var self = this;
  207. this.trace('createAnswer', JSON.stringify(constraints, null, ' '));
  208. this.peerconnection.createAnswer(
  209. function (answer) {
  210. answer = APP.simulcast.transformAnswer(answer);
  211. self.trace('createAnswerOnSuccess', dumpSDP(answer));
  212. successCallback(answer);
  213. },
  214. function(err) {
  215. self.trace('createAnswerOnFailure', err);
  216. failureCallback(err);
  217. },
  218. constraints
  219. );
  220. };
  221. TraceablePeerConnection.prototype.addIceCandidate = function (candidate, successCallback, failureCallback) {
  222. var self = this;
  223. this.trace('addIceCandidate', JSON.stringify(candidate, null, ' '));
  224. this.peerconnection.addIceCandidate(candidate);
  225. /* maybe later
  226. this.peerconnection.addIceCandidate(candidate,
  227. function () {
  228. self.trace('addIceCandidateOnSuccess');
  229. successCallback();
  230. },
  231. function (err) {
  232. self.trace('addIceCandidateOnFailure', err);
  233. failureCallback(err);
  234. }
  235. );
  236. */
  237. };
  238. TraceablePeerConnection.prototype.getStats = function(callback, errback) {
  239. if (navigator.mozGetUserMedia) {
  240. // ignore for now...
  241. if(!errback)
  242. errback = function () {
  243. }
  244. this.peerconnection.getStats(null,callback,errback);
  245. } else {
  246. this.peerconnection.getStats(callback);
  247. }
  248. };
  249. module.exports = TraceablePeerConnection;