Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

port-sniffer task #17

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions submissions/Vitamin/port-sniffer/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const help = `
Usage: sniffer.js [--help] [--ports <number>-<number>] [--host <value>]

These are commands used in sniffer application:

host Host address, IP or URL.
Examples: --host ukr.net,
--host 172.217.3.110

ports Ports range. Numbers must be more than 0 and less than 65535.
Examples: --port 30-562,
--port 1-65535.

help Show all commands.
`;

const isDefined = value => value != null && value !== false;

module.exports = { help, isDefined };
100 changes: 100 additions & 0 deletions submissions/Vitamin/port-sniffer/sniffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const Net = require('net');
const dns = require('dns').promises;
const { help, isDefined } = require('./helpers');

const [, , ...processArgs] = process.argv;
const [minPortValue, maxPortValue] = [0, 65535];

const ipToURL = async host => {
Vitaminvp marked this conversation as resolved.
Show resolved Hide resolved
try {
const result = await dns.lookup(host);
return await result.address;
Vitaminvp marked this conversation as resolved.
Show resolved Hide resolved
} catch (err) {
throw Error('Invalid host');
}
};

const isPortInRange = port => port >= minPortValue && port <= maxPortValue;

const getPortsRange = ports => {
const [firstPort, last] = ports.split('-');
const lastPort = isPortInRange(last) ? last : firstPort;
if (isPortInRange(firstPort)) {
return [firstPort, lastPort];
}
// eslint-disable-next-line no-console
console.log('Invalid ports range');
return undefined;
Vitaminvp marked this conversation as resolved.
Show resolved Hide resolved
};

const tryToConnect = (host, port) => {
const client = new Net.Socket();
client.setTimeout(300);
client.connect({ port, host });
return new Promise(resolve => {
client.on('connect', () => {
process.stdout.write('.');
client.destroy();
return resolve(port);
});
client.on('timeout', () => {
client.destroy();
return resolve(false);
Vitaminvp marked this conversation as resolved.
Show resolved Hide resolved
});
client.on('error', () => {
client.destroy();
return resolve(false);
});
});
};

const getOpenedPorts = async ({ host, firstPort, lastPort }) => {
const promises = [];
// eslint-disable-next-line no-plusplus
for (let i = firstPort; i <= lastPort; i++) {
promises.push(tryToConnect(host, i));
}
const ports = await Promise.all(promises);
return ports.filter(isDefined);
};

const parseArguments = async args => {
if (args.includes('--help')) {
// eslint-disable-next-line no-console
Vitaminvp marked this conversation as resolved.
Show resolved Hide resolved
console.log(help);
process.exit(0);
} else if (
args.length < 4 ||
!args.includes('--ports') ||
!args.includes('--host')
) {
// eslint-disable-next-line no-console
console.log('Use --help to correct input');
process.exit(1);
}
const [firstPort, lastPort] = getPortsRange(args[1]);
const host = await ipToURL(args[3]);
return { host, firstPort, lastPort };
};

const getMessageToLog = openPorts => {
let result;
if (openPorts.length > 1) {
result = `\n${openPorts} ports are opened`;
} else if (openPorts.length === 1) {
result = `\n${openPorts} port is opened`;
} else {
result = '\nAll ports in range are closed';
}
return result;
};

const sniff = async args => {
const { host, firstPort, lastPort } = await parseArguments(args);
return getOpenedPorts({ host, firstPort, lastPort });
};

sniff(processArgs)
.then(getMessageToLog)
// eslint-disable-next-line no-console
.then(console.log);