tcp-chrome-sockets.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. "use strict";
  2. var makeChannel = require('culvert');
  3. var wrapHandler = require('../lib/wrap-handler');
  4. var tcp = window.chrome.sockets.tcp;
  5. var runtime = window.chrome.runtime;
  6. module.exports = connect;
  7. function connect(host, port, onError) {
  8. port = port|0;
  9. host = String(host);
  10. if (!port || !host) throw new TypeError("host and port are required");
  11. onCreate = wrap(onCreate, onError);
  12. onConnect = wrap(onConnect, onError);
  13. onInfo = wrap(onInfo, onError);
  14. onReceive = wrap(onReceive, onError);
  15. onReceiveError = wrap(onReceiveError, onError);
  16. onData = wrapHandler(onData, onError);
  17. onWrite = wrap(onWrite, onError);
  18. var paused = false;
  19. var open = false;
  20. var socketId;
  21. var serverChannel = makeChannel();
  22. var clientChannel = makeChannel();
  23. var socket = {
  24. put: serverChannel.put,
  25. drain: serverChannel.drain,
  26. take: clientChannel.take
  27. };
  28. tcp.onReceive.addListener(onReceive);
  29. tcp.onReceiveError.addListener(onReceiveError);
  30. tcp.create(onCreate);
  31. return {
  32. put: clientChannel.put,
  33. drain: clientChannel.drain,
  34. take: serverChannel.take
  35. };
  36. function onCreate(createInfo) {
  37. socketId = createInfo.socketId;
  38. tcp.connect(socketId, host, port, onConnect);
  39. }
  40. function onConnect(result) {
  41. if (result < 0) throw new Error(runtime.lastError.message + " Connection error");
  42. tcp.getInfo(socketId, onInfo);
  43. }
  44. function onInfo(socketInfo) {
  45. if (!socketInfo.connected) {
  46. throw new Error("Connection failed");
  47. }
  48. open = true;
  49. socket.take(onData);
  50. }
  51. function onReceive(info) {
  52. if (info.socketId !== socketId) return;
  53. if (socket.put(new Uint8Array(info.data)) || paused) return;
  54. paused = true;
  55. tcp.setPaused(socketId, true);
  56. socket.drain(onDrain);
  57. }
  58. function onDrain() {
  59. if (!paused) return;
  60. paused = false;
  61. if (open) tcp.setPaused(socketId, false);
  62. }
  63. function onReceiveError(info) {
  64. if (info.socketId !== socketId) return;
  65. open = false;
  66. tcp.close(socketId);
  67. socket.put();
  68. // TODO: find a way to tell close and error apart.
  69. // throw new Error("Code " + info.resultCode + " error while receiving.");
  70. }
  71. function onData(data) {
  72. tcp.send(socketId, data.buffer, onWrite);
  73. }
  74. function onWrite(info) {
  75. if (info.resultCode < 0) {
  76. throw new Error(runtime.lastError.message + " Error writing.");
  77. }
  78. socket.take(onData);
  79. }
  80. }
  81. function wrap(fn, onError) {
  82. return function () {
  83. try {
  84. return fn.apply(this, arguments);
  85. }
  86. catch (err) {
  87. onError(err);
  88. }
  89. };
  90. }