peer.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. function Peer(options) {
  2. if (!(this instanceof Peer)) return new Peer(options);
  3. EventEmitter.call(this);
  4. options = util.extend({
  5. debug: false,
  6. peer: 'ws://localhost'
  7. }, options);
  8. this.options = options;
  9. util.debug = options.debug;
  10. this._id = null;
  11. this._socket = new WebSocket(options.ws);
  12. this._socketInit();
  13. // Connections for this peer.
  14. this.connections = {};
  15. // Queued connections to make.
  16. this._queued = [];
  17. // Make sure connections are cleaned up.
  18. window.onbeforeunload = this._cleanup;
  19. };
  20. util.inherits(Peer, EventEmitter);
  21. /** Start up websocket communications. */
  22. Peer.prototype._socketInit = function() {
  23. var self = this;
  24. this._socket.onmessage = function(event) {
  25. var message = JSON.parse(event.data);
  26. var peer = message.src;
  27. var connection = self.connections[peer];
  28. switch (message.type) {
  29. case 'ID':
  30. self._id = message.id;
  31. self._processQueue();
  32. self.emit('ready', self._id);
  33. break;
  34. case 'OFFER':
  35. var options = {
  36. metadata: message.metadata,
  37. sdp: message.sdp
  38. };
  39. var connection = new DataConnection(self._id, peer, self._socket, function(err, connection) {
  40. if (!err) {
  41. self.emit('connection', connection, message.metadata);
  42. }
  43. }, options);
  44. self.connections[peer] = connection;
  45. break;
  46. case 'ANSWER':
  47. if (connection) connection.handleSDP(message);
  48. break;
  49. case 'CANDIDATE':
  50. if (connection) connection.handleCandidate(message);
  51. break;
  52. case 'LEAVE':
  53. if (connection) connection.handleLeave();
  54. break;
  55. case 'PORT':
  56. if (browserisms == 'Firefox') {
  57. connection.handlePort(message);
  58. break;
  59. }
  60. case 'DEFAULT':
  61. util.log('PEER: unrecognized message ', message.type);
  62. break;
  63. }
  64. };
  65. this._socket.onopen = function() {
  66. // Announce as a PEER to receive an ID.
  67. self._socket.send(JSON.stringify({
  68. type: 'PEER'
  69. }));
  70. };
  71. };
  72. Peer.prototype._processQueue = function() {
  73. while (this._queued.length > 0) {
  74. var cdata = this._queued.pop();
  75. this.connect.apply(this, cdata);
  76. }
  77. };
  78. Peer.prototype._cleanup = function() {
  79. for (var peer in this.connections) {
  80. if (this.connections.hasOwnProperty(peer)) {
  81. this.connections[peer].close();
  82. }
  83. }
  84. };
  85. Peer.prototype.connect = function(peer, metadata, cb) {
  86. if (typeof metadata === 'function' && !cb) cb = metadata; metadata = false;
  87. if (!this._id) {
  88. this._queued.push(Array.prototype.slice.apply(arguments));
  89. return;
  90. }
  91. var options = {
  92. metadata: metadata
  93. };
  94. var connection = new DataConnection(this._id, peer, this._socket, cb, options);
  95. this.connections[peer] = connection;
  96. };
  97. exports.Peer = Peer;