registry.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.Registry = void 0;
  7. const dns_equal_1 = __importDefault(require("./utils/dns-equal"));
  8. const service_1 = __importDefault(require("./service"));
  9. const REANNOUNCE_MAX_MS = 60 * 60 * 1000;
  10. const REANNOUNCE_FACTOR = 3;
  11. const noop = function () { };
  12. class Registry {
  13. constructor(server) {
  14. this.services = [];
  15. this.server = server;
  16. }
  17. publish(config) {
  18. function start(service, registry, opts) {
  19. if (service.activated)
  20. return;
  21. service.activated = true;
  22. registry.services.push(service);
  23. if (!(service instanceof service_1.default))
  24. return;
  25. if (opts === null || opts === void 0 ? void 0 : opts.probe) {
  26. registry.probe(registry.server.mdns, service, (exists) => {
  27. if (exists) {
  28. if (service.stop !== undefined)
  29. service.stop();
  30. console.log(new Error('Service name is already in use on the network'));
  31. return;
  32. }
  33. registry.announce(registry.server, service);
  34. });
  35. }
  36. else {
  37. registry.announce(registry.server, service);
  38. }
  39. }
  40. function stop(service, registry, callback) {
  41. if (!callback)
  42. callback = noop;
  43. if (!service.activated)
  44. return process.nextTick(callback);
  45. if (!(service instanceof service_1.default))
  46. return process.nextTick(callback);
  47. registry.teardown(registry.server, service, callback);
  48. const index = registry.services.indexOf(service);
  49. if (index !== -1)
  50. registry.services.splice(index, 1);
  51. }
  52. const service = new service_1.default(config);
  53. service.start = start.bind(null, service, this);
  54. service.stop = stop.bind(null, service, this);
  55. service.start({ probe: config.probe !== false });
  56. return service;
  57. }
  58. unpublishAll(callback) {
  59. this.teardown(this.server, this.services, callback);
  60. this.services = [];
  61. }
  62. destroy() {
  63. this.services.map(service => service.destroyed = true);
  64. }
  65. probe(mdns, service, callback) {
  66. var sent = false;
  67. var retries = 0;
  68. var timer;
  69. const send = () => {
  70. if (!service.activated || service.destroyed)
  71. return;
  72. mdns.query(service.fqdn, 'ANY', function () {
  73. sent = true;
  74. timer = setTimeout(++retries < 3 ? send : done, 250);
  75. timer.unref();
  76. });
  77. };
  78. const onresponse = (packet) => {
  79. if (!sent)
  80. return;
  81. if (packet.answers.some(matchRR) || packet.additionals.some(matchRR))
  82. done(true);
  83. };
  84. const matchRR = (rr) => {
  85. return (0, dns_equal_1.default)(rr.name, service.fqdn);
  86. };
  87. const done = (exists) => {
  88. mdns.removeListener('response', onresponse);
  89. clearTimeout(timer);
  90. callback(!!exists);
  91. };
  92. mdns.on('response', onresponse);
  93. setTimeout(send, Math.random() * 250);
  94. }
  95. announce(server, service) {
  96. var delay = 1000;
  97. var packet = service.records();
  98. server.register(packet);
  99. const broadcast = () => {
  100. if (!service.activated || service.destroyed)
  101. return;
  102. server.mdns.respond(packet, function () {
  103. if (!service.published) {
  104. service.activated = true;
  105. service.published = true;
  106. service.emit('up');
  107. }
  108. delay = delay * REANNOUNCE_FACTOR;
  109. if (delay < REANNOUNCE_MAX_MS && !service.destroyed) {
  110. setTimeout(broadcast, delay).unref();
  111. }
  112. });
  113. };
  114. broadcast();
  115. }
  116. teardown(server, services, callback) {
  117. if (!Array.isArray(services))
  118. services = [services];
  119. services = services.filter((service) => service.activated);
  120. var records = services.flatMap(function (service) {
  121. service.activated = false;
  122. var records = service.records();
  123. records.forEach((record) => {
  124. record.ttl = 0;
  125. });
  126. return records;
  127. });
  128. if (records.length === 0)
  129. return callback && process.nextTick(callback);
  130. server.unregister(records);
  131. server.mdns.respond(records, function () {
  132. services.forEach(function (service) {
  133. service.published = false;
  134. });
  135. if (typeof callback === "function") {
  136. callback.apply(null, arguments);
  137. }
  138. });
  139. }
  140. }
  141. exports.Registry = Registry;
  142. exports.default = Registry;
  143. //# sourceMappingURL=registry.js.map