tcp-ws-proxy.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. "use strict";
  2. var makeChannel = require('culvert');
  3. var wrapHandler = require('../lib/wrap-handler');
  4. module.exports = function (proxyUrl) {
  5. if (proxyUrl[proxyUrl.length - 1] !== "/") proxyUrl += "/";
  6. return function connect(host, port, onError) {
  7. port = port|0;
  8. host = String(host);
  9. if (!port || !host) throw new TypeError("host and port are required");
  10. onData = wrapHandler(onData, onError);
  11. var serverChannel = makeChannel();
  12. var clientChannel = makeChannel();
  13. var socket = {
  14. put: serverChannel.put,
  15. drain: serverChannel.drain,
  16. take: clientChannel.take
  17. };
  18. var connected = false;
  19. var ws = new WebSocket(proxyUrl + "tcp/" + host + "/" + port);
  20. ws.binaryType = "arraybuffer";
  21. ws.onopen = wrap(onOpen, onError);
  22. ws.onclose = wrap(onClose, onError);
  23. ws.onmessage = wrap(onMessage, onError);
  24. ws.onerror = wrap(onWsError, onError);
  25. return {
  26. put: clientChannel.put,
  27. drain: clientChannel.drain,
  28. take: serverChannel.take
  29. };
  30. function onOpen() {
  31. ws.send("connect");
  32. }
  33. function onClose() {
  34. socket.put();
  35. }
  36. function onMessage(evt) {
  37. if (!connected && evt.data === "connect") {
  38. connected = true;
  39. socket.take(onData);
  40. return;
  41. }
  42. socket.put(new Uint8Array(evt.data));
  43. }
  44. function onWsError() {
  45. console.error(arguments);
  46. throw new Error("Generic websocket error");
  47. }
  48. function onData(chunk) {
  49. ws.send(chunk.buffer);
  50. socket.take(onData);
  51. }
  52. };
  53. };
  54. function wrap(fn, onError) {
  55. return function () {
  56. try {
  57. return fn.apply(this, arguments);
  58. }
  59. catch (err) {
  60. onError(err);
  61. }
  62. };
  63. }