registry.js 4.9 KB

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