sender.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.Sender = exports.ParallelSendStrategy = void 0;
  6. var _dgram = _interopRequireDefault(require("dgram"));
  7. var _dns = _interopRequireDefault(require("dns"));
  8. var _net = _interopRequireDefault(require("net"));
  9. var punycode = _interopRequireWildcard(require("punycode"));
  10. function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
  11. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; if (obj != null) { var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
  12. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  13. class ParallelSendStrategy {
  14. constructor(addresses, port, request) {
  15. this.addresses = addresses;
  16. this.port = port;
  17. this.request = request;
  18. this.socketV4 = null;
  19. this.socketV6 = null;
  20. this.onError = null;
  21. this.onMessage = null;
  22. }
  23. clearSockets() {
  24. const clearSocket = (socket, onError, onMessage) => {
  25. socket.removeListener('error', onError);
  26. socket.removeListener('message', onMessage);
  27. socket.close();
  28. };
  29. if (this.socketV4) {
  30. clearSocket(this.socketV4, this.onError, this.onMessage);
  31. this.socketV4 = null;
  32. }
  33. if (this.socketV6) {
  34. clearSocket(this.socketV6, this.onError, this.onMessage);
  35. this.socketV6 = null;
  36. }
  37. }
  38. send(cb) {
  39. let errorCount = 0;
  40. const onError = err => {
  41. errorCount++;
  42. if (errorCount === this.addresses.length) {
  43. this.clearSockets();
  44. cb(err);
  45. }
  46. };
  47. const onMessage = message => {
  48. this.clearSockets();
  49. cb(null, message);
  50. };
  51. const createDgramSocket = (udpType, onError, onMessage) => {
  52. const socket = _dgram.default.createSocket(udpType);
  53. socket.on('error', onError);
  54. socket.on('message', onMessage);
  55. return socket;
  56. };
  57. for (let j = 0; j < this.addresses.length; j++) {
  58. const udpTypeV4 = 'udp4';
  59. const udpTypeV6 = 'udp6';
  60. const udpType = this.addresses[j].family === 6 ? udpTypeV6 : udpTypeV4;
  61. let socket;
  62. if (udpType === udpTypeV4) {
  63. if (!this.socketV4) {
  64. this.socketV4 = createDgramSocket(udpTypeV4, onError, onMessage);
  65. }
  66. socket = this.socketV4;
  67. } else {
  68. if (!this.socketV6) {
  69. this.socketV6 = createDgramSocket(udpTypeV6, onError, onMessage);
  70. }
  71. socket = this.socketV6;
  72. }
  73. socket.send(this.request, 0, this.request.length, this.port, this.addresses[j].address);
  74. }
  75. this.onError = onError;
  76. this.onMessage = onMessage;
  77. }
  78. cancel() {
  79. this.clearSockets();
  80. }
  81. }
  82. exports.ParallelSendStrategy = ParallelSendStrategy;
  83. class Sender {
  84. constructor(host, port, request) {
  85. this.host = host;
  86. this.port = port;
  87. this.request = request;
  88. this.parallelSendStrategy = null;
  89. }
  90. execute(cb) {
  91. if (_net.default.isIP(this.host)) {
  92. this.executeForIP(cb);
  93. } else {
  94. this.executeForHostname(cb);
  95. }
  96. }
  97. executeForIP(cb) {
  98. this.executeForAddresses([{
  99. address: this.host,
  100. family: _net.default.isIPv6(this.host) ? 6 : 4
  101. }], cb);
  102. } // Wrapper for stubbing. Sinon does not have support for stubbing module functions.
  103. invokeLookupAll(host, cb) {
  104. _dns.default.lookup(punycode.toASCII(host), {
  105. all: true
  106. }, cb);
  107. }
  108. executeForHostname(cb) {
  109. this.invokeLookupAll(this.host, (err, addresses) => {
  110. if (err) {
  111. return cb(err);
  112. }
  113. this.executeForAddresses(addresses, cb);
  114. });
  115. } // Wrapper for stubbing creation of Strategy object. Sinon support for constructors
  116. // seems limited.
  117. createParallelSendStrategy(addresses, port, request) {
  118. return new ParallelSendStrategy(addresses, port, request);
  119. }
  120. executeForAddresses(addresses, cb) {
  121. this.parallelSendStrategy = this.createParallelSendStrategy(addresses, this.port, this.request);
  122. this.parallelSendStrategy.send(cb);
  123. }
  124. cancel() {
  125. if (this.parallelSendStrategy) {
  126. this.parallelSendStrategy.cancel();
  127. }
  128. }
  129. }
  130. exports.Sender = Sender;