tailscale_tun.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. const lazyRunIpn = async () => {
  24. const wasmUrl = new URL("tailscale.wasm", import.meta.url);
  25. const go = new window.Go();
  26. let {instance} = await fetch(wasmUrl).then(x => x.arrayBuffer()).then(x => WebAssembly.instantiate(x,go.importObject));
  27. go.run(instance);
  28. const sessionStateStorage = {
  29. setState(id, value) {
  30. window.sessionStorage[`ipn-state-${id}`] = value
  31. },
  32. getState(id) {
  33. return window.sessionStorage[`ipn-state-${id}`] || ""
  34. },
  35. }
  36. ipn = newIPN({
  37. // Persist IPN state in sessionStorage in development, so that we don't need
  38. // to re-authorize every time we reload the page.
  39. //stateStorage: sessionStateStorage,
  40. });
  41. const setupIpStack = () => {
  42. ipn.tun.onmessage = function(ev) {
  43. IpStack.input(ev.data)
  44. };
  45. IpStack.output(function(p){
  46. ipn.tun.postMessage(p, [p.buffer]);
  47. });
  48. };
  49. setupIpStack();
  50. ipn.run({
  51. notifyState: (s) => listeners.onstateupdate(s),
  52. notifyNetMap: (s) => {
  53. const netMap = JSON.parse(s);
  54. listeners.onnetmap(netMap);
  55. const newLocalIp = netMap.self.addresses[0];
  56. if (localIp != newLocalIp)
  57. {
  58. localIp = newLocalIp;
  59. try{
  60. IpStack.up({localIp, dnsIp, ipMap: {
  61. ["127.0.0.53"]: dnsIp,
  62. [dnsIp]: "127.0.0.53",
  63. }});
  64. }catch(e){
  65. console.log(e);
  66. debugger;
  67. }
  68. }
  69. },
  70. notifyBrowseToURL: (l) => listeners.onloginurl(l),
  71. });
  72. };
  73. return {
  74. connect: IpStack.connect,
  75. listen: IpStack.listen,
  76. bind: IpStack.bind,
  77. parseIP: IpStack.parseIP,
  78. resolve: IpStack.resolve,
  79. up: async (conf) => {
  80. if (ipn == null) {
  81. await lazyRunIpn();
  82. }
  83. ipn.up(conf);
  84. localIp = null;
  85. dnsIp = conf.dnsIp || "127.0.0.53";
  86. },
  87. down: () => {
  88. ipn.down();
  89. IpStack.down();
  90. },
  91. login: () => ipn.login(),
  92. logout: () => ipn.logout(),
  93. listeners
  94. };
  95. }