registry.js 4.8 KB

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