123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.SrvPoller = exports.SrvPollingEvent = void 0;
- const dns = require("dns");
- const error_1 = require("../error");
- const logger_1 = require("../logger");
- const mongo_types_1 = require("../mongo_types");
- const utils_1 = require("../utils");
- /**
- * Determines whether a provided address matches the provided parent domain in order
- * to avoid certain attack vectors.
- *
- * @param srvAddress - The address to check against a domain
- * @param parentDomain - The domain to check the provided address against
- * @returns Whether the provided address matches the parent domain
- */
- function matchesParentDomain(srvAddress, parentDomain) {
- const regex = /^.*?\./;
- const srv = `.${srvAddress.replace(regex, '')}`;
- const parent = `.${parentDomain.replace(regex, '')}`;
- return srv.endsWith(parent);
- }
- /**
- * @internal
- * @category Event
- */
- class SrvPollingEvent {
- constructor(srvRecords) {
- this.srvRecords = srvRecords;
- }
- hostnames() {
- return new Set(this.srvRecords.map(r => utils_1.HostAddress.fromSrvRecord(r).toString()));
- }
- }
- exports.SrvPollingEvent = SrvPollingEvent;
- /** @internal */
- class SrvPoller extends mongo_types_1.TypedEventEmitter {
- constructor(options) {
- var _a, _b, _c;
- super();
- if (!options || !options.srvHost) {
- throw new error_1.MongoRuntimeError('Options for SrvPoller must exist and include srvHost');
- }
- this.srvHost = options.srvHost;
- this.srvMaxHosts = (_a = options.srvMaxHosts) !== null && _a !== void 0 ? _a : 0;
- this.srvServiceName = (_b = options.srvServiceName) !== null && _b !== void 0 ? _b : 'mongodb';
- this.rescanSrvIntervalMS = 60000;
- this.heartbeatFrequencyMS = (_c = options.heartbeatFrequencyMS) !== null && _c !== void 0 ? _c : 10000;
- this.logger = new logger_1.Logger('srvPoller', options);
- this.haMode = false;
- this.generation = 0;
- this._timeout = undefined;
- }
- get srvAddress() {
- return `_${this.srvServiceName}._tcp.${this.srvHost}`;
- }
- get intervalMS() {
- return this.haMode ? this.heartbeatFrequencyMS : this.rescanSrvIntervalMS;
- }
- start() {
- if (!this._timeout) {
- this.schedule();
- }
- }
- stop() {
- if (this._timeout) {
- clearTimeout(this._timeout);
- this.generation += 1;
- this._timeout = undefined;
- }
- }
- schedule() {
- if (this._timeout) {
- clearTimeout(this._timeout);
- }
- this._timeout = setTimeout(() => this._poll(), this.intervalMS);
- }
- success(srvRecords) {
- this.haMode = false;
- this.schedule();
- this.emit(SrvPoller.SRV_RECORD_DISCOVERY, new SrvPollingEvent(srvRecords));
- }
- failure(message, obj) {
- this.logger.warn(message, obj);
- this.haMode = true;
- this.schedule();
- }
- parentDomainMismatch(srvRecord) {
- this.logger.warn(`parent domain mismatch on SRV record (${srvRecord.name}:${srvRecord.port})`, srvRecord);
- }
- _poll() {
- const generation = this.generation;
- dns.resolveSrv(this.srvAddress, (err, srvRecords) => {
- if (generation !== this.generation) {
- return;
- }
- if (err) {
- this.failure('DNS error', err);
- return;
- }
- const finalAddresses = [];
- for (const record of srvRecords) {
- if (matchesParentDomain(record.name, this.srvHost)) {
- finalAddresses.push(record);
- }
- else {
- this.parentDomainMismatch(record);
- }
- }
- if (!finalAddresses.length) {
- this.failure('No valid addresses found at host');
- return;
- }
- this.success(finalAddresses);
- });
- }
- }
- exports.SrvPoller = SrvPoller;
- /** @event */
- SrvPoller.SRV_RECORD_DISCOVERY = 'srvRecordDiscovery';
- //# sourceMappingURL=srv_polling.js.map
|