wsproto.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. ;(function(){
  2. /*
  3. HOW TO USE:
  4. 1. On your HTML include gun and this file:
  5. <script src="gun.js"></script>
  6. <script src="lib/wsproto.js"></script>
  7. 2. Initiate GUN with default WebSocket turned off:
  8. var gun = Gun({WebSocket: false});
  9. */
  10. var WebSocket;
  11. if(typeof window !== 'undefined'){
  12. WebSocket = window.WebSocket || window.webkitWebSocket || window.mozWebSocket;
  13. } else {
  14. return;
  15. }
  16. Gun.on('opt', function(ctx){
  17. this.to.next(ctx);
  18. var opt = ctx.opt;
  19. if(ctx.once){ return }
  20. opt.wsc = opt.wsc || {protocols:[]}; // for d3x0r!
  21. var ws = opt.ws || (opt.ws = {}); ws.who = 0;
  22. Gun.obj.map(opt.peers, function(){ ++ws.who });
  23. if(ctx.once){ return }
  24. var batch;
  25. ctx.on('out', function(at){
  26. this.to.next(at);
  27. if(at.ws && 1 == ws.who){ return } // performance hack for reducing echoes.
  28. batch = JSON.stringify(at);
  29. if(ws.drain){
  30. ws.drain.push(batch);
  31. return;
  32. }
  33. ws.drain = [];
  34. setTimeout(function(){
  35. if(!ws.drain){ return }
  36. var tmp = ws.drain;
  37. ws.drain = null;
  38. if(!tmp.length){ return }
  39. batch = JSON.stringify(tmp);
  40. Gun.obj.map(opt.peers, send, ctx);
  41. }, opt.wait || 1);
  42. Gun.obj.map(opt.peers, send, ctx);
  43. });
  44. function send(peer){
  45. var ctx = this, msg = batch;
  46. var wire = peer.wire || open(peer, ctx);
  47. if(!wire){ return }
  48. if(wire.readyState === wire.OPEN){
  49. wire.send(msg);
  50. return;
  51. }
  52. (peer.queue = peer.queue || []).push(msg);
  53. }
  54. function receive(msg, peer, ctx){
  55. if(!ctx || !msg){ return }
  56. try{msg = JSON.parse(msg.data || msg);
  57. }catch(e){}
  58. if(msg instanceof Array){
  59. var i = 0, m;
  60. while(m = msg[i++]){
  61. receive(m, peer, ctx);
  62. }
  63. return;
  64. }
  65. if(1 == ws.who){ msg.ws = noop } // If there is only 1 client, just use noop since it doesn't matter.
  66. ctx.on('in', msg);
  67. }
  68. function open(peer, as){
  69. if(!peer || !peer.url){ return }
  70. var url = peer.url.replace('http', 'ws');
  71. var wire = peer.wire = new WebSocket(url, as.opt.wsc.protocols, as.opt.wsc);
  72. wire.onclose = function(){
  73. reconnect(peer, as);
  74. };
  75. wire.onerror = function(error){
  76. reconnect(peer, as); // placement?
  77. if(!error){ return }
  78. if(error.code === 'ECONNREFUSED'){
  79. //reconnect(peer, as);
  80. }
  81. };
  82. wire.onopen = function(){
  83. var queue = peer.queue;
  84. peer.queue = [];
  85. Gun.obj.map(queue, function(msg){
  86. batch = msg;
  87. send.call(as, peer);
  88. });
  89. }
  90. wire.onmessage = function(msg){
  91. receive(msg, peer, as); // diff: peer not wire!
  92. };
  93. return wire;
  94. }
  95. function reconnect(peer, as){
  96. clearTimeout(peer.defer);
  97. peer.defer = setTimeout(function(){
  98. open(peer, as);
  99. }, 2 * 1000);
  100. }
  101. });
  102. var noop = function(){};
  103. }());