p2p-network.html 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. <link rel="import" href="p2p-network-imports.html">
  2. <link rel="import" href="../../../bower_components/iron-localstorage/iron-localstorage.html">
  3. <dom-module id="p2p-network">
  4. <template>
  5. <iron-localstorage name="peer-id" value="{{me}}" id="meStorage">
  6. </iron-localstorage>
  7. <iron-localstorage name="peers" value="{{peers}}" on-iron-localstorage-load-empty="initializeDefaultPeers">
  8. </iron-localstorage>
  9. </template>
  10. <script>
  11. 'use strict';
  12. Polymer({
  13. is: 'p2p-network',
  14. properties: {
  15. me: {
  16. type: String,
  17. notify: true,
  18. observer: '_initialize'
  19. },
  20. peers: {
  21. type: Array,
  22. value: [],
  23. notify: true,
  24. },
  25. peer: {
  26. value: 'loading',
  27. notify: true
  28. }
  29. },
  30. attached: function() {
  31. this._connectedPeers = {};
  32. this._initCallbacks = [];
  33. this._unsendMsgs = {};
  34. window.onunload = window.onbeforeunload = function() {
  35. if (!!this._peer && !this._peer.destroyed) {
  36. this._peer.destroy();
  37. }
  38. }.bind(this);
  39. },
  40. _initialize: function(me) {
  41. if (!this.initialized && this.$.meStorage._loaded) {
  42. var options = {
  43. host: 'yawim.com',
  44. port: 443 ,
  45. path:'peerjs',
  46. secure: true
  47. };
  48. me = me ? me : undefined;
  49. me = me === 'null' ? undefined : me;
  50. this._peer = new Peer(me, options);
  51. this._peer.on('open', function(id) {
  52. console.log('My peer ID is: ' + id);
  53. this.set('me', id);
  54. this._peerOpen = true;
  55. this._initCallbacks.forEach(function(cb) {
  56. cb();
  57. });
  58. }.bind(this));
  59. this._peer.on('connection', this.connect.bind(this));
  60. this._peer.on('error', function(err) {
  61. console.error(err);
  62. //ugly hack to find out error type
  63. if (err.message.indexOf('Could not connect to peer') > -1) {
  64. delete this._connectedPeers[this.peer];
  65. this.set('peer', 'error');
  66. return;
  67. }
  68. if (err.message.indexOf('Lost connection to server') > -1) {
  69. this._peer.destroy();
  70. this.initialized = false;
  71. this._connectedPeers = {};
  72. this.set('me', me);
  73. this._initialize(this.me);
  74. return;
  75. }
  76. }.bind(this));
  77. }
  78. this.initialized = true;
  79. },
  80. connect: function(c) {
  81. var peer = c.peer;
  82. if (c.label === 'chat') {
  83. c.on('data', function(data) {
  84. this.addToHistory(c.peer, data);
  85. this.sendIReceived(c.peer, data);
  86. }.bind(this));
  87. c.on('close', function() {
  88. console.log(c.peer + ' has left the chat.');
  89. delete this._connectedPeers[peer];
  90. }.bind(this));
  91. if(!this.peers){
  92. this.set('peers',[]);
  93. }
  94. var peerInContacts = this.peers.some(function(p) {
  95. return p.peer === peer;
  96. });
  97. if (!peerInContacts) {
  98. this.push('peers', {
  99. peer: peer
  100. });
  101. }
  102. this._connectedPeers[peer] = 1;
  103. this.fire('connected-to-peer', peer);
  104. }
  105. if (c.label === 'file') {
  106. c.on('data', function(data) {
  107. // If we're getting a file, create a URL for it.
  108. console.log('received!', data);
  109. this.fire('file-received', {
  110. peer: peer,
  111. url: data.url,
  112. name: data.name,
  113. });
  114. }.bind(this));
  115. }
  116. if (c.label === 'received-channel') {
  117. c.on('data', function(data) {
  118. this._peerReceivedMsg(c.peer, data);
  119. }.bind(this));
  120. }
  121. //send unsend messages
  122. if (this._unsendMsgs[peer]) {
  123. this._unsendMsgs[peer].forEach(function(msg) {
  124. this.send(peer, msg);
  125. }.bind(this));
  126. }
  127. },
  128. connectToPeer: (function() {
  129. function request(requestedPeer) {
  130. return function() {
  131. var c = this._peer.connect(requestedPeer, {
  132. label: 'chat',
  133. metadata: {
  134. message: 'hi i want to chat with you!'
  135. }
  136. });
  137. c.on('open', function() {
  138. this.connect(c);
  139. }.bind(this));
  140. var c1 = this._peer.connect(requestedPeer, {
  141. label: 'received-channel',
  142. });
  143. c1.on('open', function() {
  144. this.connect(c1);
  145. }.bind(this));
  146. var f = this._peer.connect(requestedPeer, {
  147. label: 'file',
  148. reliable: true
  149. });
  150. f.on('open', function() {
  151. this.connect(f);
  152. }.bind(this));
  153. f.on('error', function(err) {
  154. console.log(err);
  155. });
  156. };
  157. }
  158. return function(requestedPeer) {
  159. if (!this._connectedPeers[requestedPeer]) {
  160. this.set('peer', 'loading');
  161. if (this._peerOpen) {
  162. request(requestedPeer).bind(this)();
  163. } else {
  164. this._initCallbacks.push(request(requestedPeer).bind(this));
  165. }
  166. }
  167. };
  168. }()),
  169. send: function(peerId, msg) {
  170. var conns = this._peer.connections[peerId];
  171. if (conns) {
  172. for (var i = 0; i < conns.length; i++) {
  173. var conn = conns[i];
  174. if (conn.label === 'chat') {
  175. this._addToUnsendMsgs(peerId, msg);
  176. conn.send(msg);
  177. this.addToHistory(conn.peer, msg);
  178. }
  179. }
  180. } else {
  181. this._addToUnsendMsgs(peerId, msg);
  182. this.connectToPeer(peerId);
  183. }
  184. },
  185. sendFile: function(peerId, file) {
  186. var conns = this._peer.connections[peerId];
  187. if (conns) {
  188. for (var i = 0; i < conns.length; i++) {
  189. var conn = conns[i];
  190. if (conn.label === 'file') {
  191. conn.send(file);
  192. console.log('file send');
  193. }
  194. }
  195. }
  196. },
  197. _addToUnsendMsgs: function(peerId, msg) {
  198. if (!this._unsendMsgs[peerId]) {
  199. this._unsendMsgs[peerId] = [];
  200. }
  201. if (this._unsendMsgs[peerId].indexOf(msg) === -1) {
  202. this._unsendMsgs[peerId].push(msg);
  203. console.log('added unsend', msg);
  204. }
  205. },
  206. sendIReceived: function(peerId, msg) {
  207. var conns = this._peer.connections[peerId];
  208. if (conns) {
  209. for (var i = 0; i < conns.length; i++) {
  210. var conn = conns[i];
  211. if (conn.label === 'received-channel') {
  212. conn.send(msg);
  213. }
  214. }
  215. } else {
  216. this.connectToPeer(peerId);
  217. }
  218. },
  219. addToHistory: function(peerId, msg) {
  220. console.log('send message', msg);
  221. this.fire('new-message', msg);
  222. },
  223. initializeDefaultPeers: function() {
  224. this.peers = [];
  225. },
  226. _peerReceivedMsg: function(peerId, msg) {
  227. console.log('received', peerId, msg);
  228. var i = this._unsendMsgs[peerId].indexOf(msg);
  229. this._unsendMsgs[peerId].splice(i, 1);
  230. }
  231. });
  232. </script>
  233. </dom-module>