peer.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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. server: 'localhost'
  7. }, options);
  8. this.options = options;
  9. util.debug = options.debug;
  10. this._id = options.id;
  11. // Not used unless using cloud server.
  12. this._api_key = options.api_key;
  13. this._socket = new WebSocket('ws://' + options.server);
  14. this._socketInit();
  15. // Connections for this peer.
  16. this.connections = {};
  17. // Queued connections to make.
  18. this._queued = [];
  19. // If no ID provided, get a unique ID from server.
  20. // Make sure connections are cleaned up.
  21. window.onbeforeunload = this._cleanup;
  22. };
  23. util.inherits(Peer, EventEmitter);
  24. /** Start up websocket communications. */
  25. Peer.prototype._socketInit = function() {
  26. var self = this;
  27. this._socket.onmessage = function(event) {
  28. var message = JSON.parse(event.data);
  29. var peer = message.src;
  30. var connection = self.connections[peer];
  31. switch (message.type) {
  32. case 'ID':
  33. self._id = message.id;
  34. self._processQueue();
  35. self.emit('ready', self._id);
  36. break;
  37. case 'OFFER':
  38. var options = {
  39. metadata: message.metadata,
  40. sdp: message.sdp
  41. };
  42. var connection = new DataConnection(self._id, peer, self._socket, function(err, connection) {
  43. if (!err) {
  44. self.emit('connection', connection, message.metadata);
  45. }
  46. }, options);
  47. self.connections[peer] = connection;
  48. break;
  49. case 'ANSWER':
  50. if (connection) connection.handleSDP(message);
  51. break;
  52. case 'CANDIDATE':
  53. if (connection) connection.handleCandidate(message);
  54. break;
  55. case 'LEAVE':
  56. if (connection) connection.handleLeave();
  57. break;
  58. case 'PORT':
  59. if (browserisms == 'Firefox') {
  60. connection.handlePort(message);
  61. break;
  62. }
  63. case 'DEFAULT':
  64. util.log('PEER: unrecognized message ', message.type);
  65. break;
  66. }
  67. };
  68. this._socket.onopen = function() {
  69. self._use_socket = true;
  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;