Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. 'use strict';
  2. const net = require('net');
  3. class Locked extends Error {
  4. constructor(port) {
  5. super(`${port} is locked`);
  6. }
  7. }
  8. const lockedPorts = {
  9. old: new Set(),
  10. young: new Set()
  11. };
  12. // On this interval, the old locked ports are discarded,
  13. // the young locked ports are moved to old locked ports,
  14. // and a new young set for locked ports are created.
  15. const releaseOldLockedPortsIntervalMs = 1000 * 15;
  16. // Lazily create interval on first use
  17. let interval;
  18. const getAvailablePort = options => new Promise((resolve, reject) => {
  19. const server = net.createServer();
  20. server.unref();
  21. server.on('error', reject);
  22. server.listen(options, () => {
  23. const {port} = server.address();
  24. server.close(() => {
  25. resolve(port);
  26. });
  27. });
  28. });
  29. const portCheckSequence = function * (ports) {
  30. if (ports) {
  31. yield * ports;
  32. }
  33. yield 0; // Fall back to 0 if anything else failed
  34. };
  35. module.exports = async options => {
  36. let ports;
  37. if (options) {
  38. ports = typeof options.port === 'number' ? [options.port] : options.port;
  39. }
  40. if (interval === undefined) {
  41. interval = setInterval(() => {
  42. lockedPorts.old = lockedPorts.young;
  43. lockedPorts.young = new Set();
  44. }, releaseOldLockedPortsIntervalMs);
  45. // Does not exist in some environments (Electron, Jest jsdom env, browser, etc).
  46. if (interval.unref) {
  47. interval.unref();
  48. }
  49. }
  50. for (const port of portCheckSequence(ports)) {
  51. try {
  52. let availablePort = await getAvailablePort({...options, port}); // eslint-disable-line no-await-in-loop
  53. while (lockedPorts.old.has(availablePort) || lockedPorts.young.has(availablePort)) {
  54. if (port !== 0) {
  55. throw new Locked(port);
  56. }
  57. availablePort = await getAvailablePort({...options, port}); // eslint-disable-line no-await-in-loop
  58. }
  59. lockedPorts.young.add(availablePort);
  60. return availablePort;
  61. } catch (error) {
  62. if (!['EADDRINUSE', 'EACCES'].includes(error.code) && !(error instanceof Locked)) {
  63. throw error;
  64. }
  65. }
  66. }
  67. throw new Error('No available ports found');
  68. };
  69. module.exports.makeRange = (from, to) => {
  70. if (!Number.isInteger(from) || !Number.isInteger(to)) {
  71. throw new TypeError('`from` and `to` must be integer numbers');
  72. }
  73. if (from < 1024 || from > 65535) {
  74. throw new RangeError('`from` must be between 1024 and 65535');
  75. }
  76. if (to < 1024 || to > 65536) {
  77. throw new RangeError('`to` must be between 1024 and 65536');
  78. }
  79. if (to < from) {
  80. throw new RangeError('`to` must be greater than or equal to `from`');
  81. }
  82. const generator = function * (from, to) {
  83. for (let port = from; port <= to; port++) {
  84. yield port;
  85. }
  86. };
  87. return generator(from, to);
  88. };