gui.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. const path = require('path');
  2. const fs = require('fs');
  3. const os = require('os');
  4. const debug = require('../server/node_modules/debug')('oasis');
  5. const lodash = require('../server/node_modules/lodash');
  6. const ssbClient = require('../server/node_modules/ssb-client');
  7. const ssbConfig = require('../server/node_modules/ssb-config');
  8. const ssbKeys = require('../server/node_modules/ssb-keys');
  9. const { printMetadata } = require('../server/ssb_metadata');
  10. const updateFlagPath = path.join(__dirname, "../server/.update_required");
  11. let internalSSB = null;
  12. try {
  13. const { server } = require('../server/SSB_server');
  14. internalSSB = server;
  15. } catch {}
  16. if (process.env.OASIS_TEST) {
  17. ssbConfig.path = fs.mkdtempSync(path.join(os.tmpdir(), "oasis-"));
  18. ssbConfig.keys = ssbKeys.generate();
  19. }
  20. const socketPath = path.join(ssbConfig.path, "socket");
  21. const publicInteger = ssbConfig.keys.public.replace(".ed25519", "");
  22. const remote = `unix:${socketPath}~noauth:${publicInteger}`;
  23. const connect = (options) =>
  24. new Promise((resolve, reject) => {
  25. ssbClient(process.env.OASIS_TEST ? ssbConfig.keys : null, options)
  26. .then(resolve)
  27. .catch(reject);
  28. });
  29. let closing = false;
  30. let clientHandle;
  31. const attemptConnectionWithBackoff = (attempt = 1) => {
  32. const maxAttempts = 5;
  33. const delay = Math.min(1000 * Math.pow(2, attempt), 10000);
  34. return new Promise((resolve, reject) => {
  35. connect({ remote })
  36. .then(resolve)
  37. .catch((error) => {
  38. if (attempt >= maxAttempts) {
  39. return reject(new Error("Failed to connect after multiple attempts"));
  40. }
  41. setTimeout(() => {
  42. attemptConnectionWithBackoff(attempt + 1).then(resolve).catch(reject);
  43. }, delay);
  44. });
  45. });
  46. };
  47. let pendingConnection = null;
  48. const ensureConnection = (customConfig) => {
  49. if (pendingConnection === null) {
  50. pendingConnection = new Promise((resolve) => {
  51. setTimeout(() => {
  52. attemptConnectionWithBackoff()
  53. .then(resolve)
  54. .catch(() => {
  55. resolve(null);
  56. });
  57. });
  58. });
  59. const cancel = () => (pendingConnection = null);
  60. pendingConnection.then(cancel, cancel);
  61. }
  62. return pendingConnection;
  63. };
  64. module.exports = ({ offline, port = 3000, host = 'localhost', isPublic = false }) => {
  65. const customConfig = JSON.parse(JSON.stringify(ssbConfig));
  66. if (offline === true) {
  67. lodash.set(customConfig, "conn.autostart", false);
  68. }
  69. lodash.set(
  70. customConfig,
  71. "conn.hops",
  72. lodash.get(ssbConfig, "conn.hops", lodash.get(ssbConfig.friends, "hops", 0))
  73. );
  74. const cooler = {
  75. open() {
  76. return new Promise((resolve, reject) => {
  77. if (internalSSB) {
  78. const { printMetadata, colors } = require('../server/ssb_metadata');
  79. printMetadata('OASIS GUI', colors.yellow, port, host, offline, isPublic);
  80. return resolve(internalSSB);
  81. }
  82. if (clientHandle && clientHandle.closed === false) {
  83. return resolve(clientHandle);
  84. }
  85. ensureConnection(customConfig).then((ssb) => {
  86. if (!ssb) return reject(new Error("No SSB server available"));
  87. clientHandle = ssb;
  88. if (closing) {
  89. cooler.close();
  90. reject(new Error("Closing Oasis"));
  91. } else {
  92. const { printMetadata, colors } = require('../server/ssb_metadata');
  93. printMetadata('OASIS GUI', colors.yellow, port, host, offline, isPublic);
  94. resolve(ssb);
  95. }
  96. }).catch(reject);
  97. });
  98. },
  99. close() {
  100. closing = true;
  101. if (clientHandle && clientHandle.closed === false) {
  102. clientHandle.close();
  103. }
  104. },
  105. };
  106. return cooler;
  107. };