tailscale_tun.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import "./wasm_exec.js";
  2. import ipStackAwait from "./ipstack.js";
  3. export const State = {
  4. NoState: 0,
  5. InUseOtherUser: 1,
  6. NeedsLogin: 2,
  7. NeedsMachineAuth: 3,
  8. Stopped: 4,
  9. Starting: 5,
  10. Running: 6,
  11. };
  12. export async function init() {
  13. const {IpStack} = await ipStackAwait();
  14. IpStack.init();
  15. const listeners = {
  16. onstateupdate: () => {},
  17. onnetmap: () => {},
  18. onloginurl: () => {},
  19. }
  20. let ipn = null;
  21. let localIp = null;
  22. let dnsIp = null;
  23. let ipMap = null;
  24. const lazyRunIpn = async (conf) => {
  25. const wasmUrl = new URL("tailscale.wasm", import.meta.url);
  26. const go = new self.Go();
  27. let {instance} = await fetch(wasmUrl).then(x => x.arrayBuffer()).then(x => WebAssembly.instantiate(x,go.importObject));
  28. go.run(instance);
  29. const sessionStateStorage = {
  30. setState(id, value) {
  31. window.sessionStorage[`ipn-state-${id}`] = value
  32. },
  33. getState(id) {
  34. return window.sessionStorage[`ipn-state-${id}`] || ""
  35. },
  36. }
  37. ipn = newIPN(conf, {
  38. // Persist IPN state in sessionStorage in development, so that we don't need
  39. // to re-authorize every time we reload the page.
  40. //stateStorage: sessionStateStorage,
  41. });
  42. const setupIpStack = () => {
  43. ipn.tun.onmessage = function(ev) {
  44. IpStack.input(ev.data)
  45. };
  46. IpStack.output(function(p){
  47. ipn.tun.postMessage(p, [p.buffer]);
  48. });
  49. };
  50. setupIpStack();
  51. ipn.run({
  52. notifyState: (s) => listeners.onstateupdate(s),
  53. notifyNetMap: (s) => {
  54. const netMap = JSON.parse(s);
  55. listeners.onnetmap(netMap);
  56. const newLocalIp = netMap.self.addresses[0];
  57. if (localIp != newLocalIp)
  58. {
  59. localIp = newLocalIp;
  60. try{
  61. IpStack.up({localIp, dnsIp, ipMap});
  62. }catch(e){
  63. console.log(e);
  64. debugger;
  65. }
  66. }
  67. },
  68. notifyBrowseToURL: (l) => listeners.onloginurl(l),
  69. });
  70. };
  71. return {
  72. tcpSocket: IpStack.TCPSocket,
  73. udpSocket: IpStack.UDPSocket,
  74. parseIP: IpStack.parseIP,
  75. dumpIP: IpStack.dumpIP,
  76. resolve: IpStack.resolve,
  77. up: async (conf) => {
  78. if (ipn == null) {
  79. await lazyRunIpn(conf);
  80. }
  81. ipn.up(conf);
  82. localIp = null;
  83. dnsIp = conf.dnsIp || "127.0.0.53";
  84. ipMap = conf.ipMap
  85. },
  86. down: () => {
  87. ipn.down();
  88. IpStack.down();
  89. },
  90. login: () => ipn.login(),
  91. logout: () => ipn.logout(),
  92. listeners
  93. };
  94. }