Conversation
lempiy
left a comment
There was a problem hiding this comment.
Nice job, now try to improve your code quality.
|
|
||
| function check(host, port, callback) { | ||
| var socket = Net.createConnection(port, host); | ||
| var timer = setTimeout(function () { |
There was a problem hiding this comment.
socket has built-in api for timeout https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback
| var timeout = 300; | ||
|
|
||
| function check(host, port, callback) { | ||
| var socket = Net.createConnection(port, host); |
There was a problem hiding this comment.
Try to wrap this function in promise and print to console from caller function
| } | ||
|
|
||
| function run_ports(){ | ||
| check(host,lower_port, function next_check(result) { |
There was a problem hiding this comment.
As mentioned above try to use Promises chaining instead of callbacks with recursion.
There was a problem hiding this comment.
Sure, but can you tell me more about why this is better??
There was a problem hiding this comment.
-
Callbacks usage may lead to "callback-hell".
https://medium.com/codebuddies/getting-to-know-asynchronous-javascript-callbacks-promises-and-async-await-17e0673281ee -
In your example you have "circle" references, which, in some cases, may lead to memory leaks like this:
Of course, it may not be the case, but I would advice, to avoid such kind of "double self referenced recursion". Especially, if some one else (other dev) may add something to your code.
| var lower_port = 0; | ||
| var higher_port = 65535; | ||
| var port_list = []; | ||
| var timeout = 300; |
There was a problem hiding this comment.
No need to use var if you are not looking for exactly function-wide scope. It's better to be consistent and use let instead. Or maybe try to reduce amount of mutable global variables by passing them as arguments from function-to-function.
|
|
||
| function run_ports(){ | ||
| check(host,lower_port, function next_check(result) { | ||
| if (lower_port == higher_port) { |
There was a problem hiding this comment.
Its better to always use === to prevent assertion bugs
| }) | ||
| }; | ||
|
|
||
| switch (process.argv[2]) { |
There was a problem hiding this comment.
Don't use global instructions in your code - wrap them into main function
There was a problem hiding this comment.
Done, and can you tell me why avoid to use them? thanks!
There was a problem hiding this comment.
- Modularize — one function per task
https://www.w3.org/wiki/JavaScript_best_practices - It makes your variables scope more clear and may prevent some unexpected variables shadowing.
- In this case you have only one module, but in more complex apps you may have many other modules. Your code outside functions will be executed upon require/import, which is hard to track in big apps.
| } | ||
| } | ||
| else { | ||
| check(host,++lower_port,next_check); |
There was a problem hiding this comment.
Double self-referencing (check, next_check) is not obvious and a bit dangerous code.
There was a problem hiding this comment.
Ok I will change this, but what you are saying is that, recursion with the same function is not a good practice even if I use a call back, I think after I destroy the socket there is nothing behind I start with the new function. but no problem consider this done. Thanks :D
There was a problem hiding this comment.
I'm not saying you have leak here, I'm just emphasising that it's easier to make mistake in such code.
| } | ||
| } | ||
| else { | ||
| check(host,++lower_port,next_check); |
There was a problem hiding this comment.
I'm not saying you have leak here, I'm just emphasising that it's easier to make mistake in such code.
| var ports = [2]; | ||
| ports = process.argv[3].split('-'); | ||
| lower_port = ports[0]; | ||
| higher_port = ports[1]; |
There was a problem hiding this comment.
const [lower_port, higher_port] = process.argv[3].split('-');Also check for errors (string with no '-', non-number values)
|
@Chikus great job so far! Please check code quality guidelines and fix the style of your code. |
lempiy
left a comment
There was a problem hiding this comment.
Looks much better for me 👍 , see more comments bellow.
| resolve(port); | ||
| }); | ||
| socket.on('error', function fail() { | ||
| throw new Error('Error in Socket, wrong host \n'); |
| throw new Error('Ports no defined \n'); | ||
| } | ||
|
|
||
| function checkHost(host) { |
There was a problem hiding this comment.
No need to declare this functions inside sniffer function. Move functions to module scope (checkPorts, runPorts, checkHost, checkServer).
There was a problem hiding this comment.
if import the function sniffer, I will not hava access to this others functions, I just did that for comfort from the user he just execute the funcion, but Ok i will change the scope.
There was a problem hiding this comment.
You won't import sniffer function and any other function here, since they are not exported.
| return null; | ||
| } | ||
|
|
||
| switch (arg[2]) { |
There was a problem hiding this comment.
I think it would be great to create parseArgument function, that will return an object with parsed args. parseArgument may be called from sniffer (root) function and depending on returned object we will decide how to call runPorts .
It will make you code more flexible and extendable.
|
|
||
| function checkHost(host) { | ||
| if (host) { | ||
| const domains = host.split('.'); |
There was a problem hiding this comment.
Use dns node package to validate domain
There was a problem hiding this comment.
const dns = require('dns').promises;
async function checkHost(host) {
try {
return (await dns.resolve(host)).address;
} catch (err) {
throw new Error('Wrong host');
}
}There was a problem hiding this comment.
I used this function but I consider it is not necessary to add, for example if you set in argument --host 10.4 this function will not throw any error, it will fill with zeros the IP 10.0.0.4, also I had some issues with my node version, but when I maked it work, I see it is doing the same that net.socket does, so for this consideration I didn't implemented.
There was a problem hiding this comment.
DNS is not the same as socket. Socket uses TCP connection or IPC streaming. DNS is domain resolve system built on top of UDP with fallback to TCP.
If you don't want to use it - it's ok, but your current host validation is incorrect and looks ugly. Here example of correct (RFC) regexp for hostname (https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address). As you see its pretty big, you may use this if you want or check for Invalid host error in socket.error event to break the loop on first connect to wrong host.
There was a problem hiding this comment.
You are right, Socket doesnt do the same as DNS, but what I tried to said is that socket
= required('net') inside of socket they are doing DNS validation, You can checked in this repo. https://github.com/nodejs/node/blob/master/lib/net.js , other wise how socket can work when you provide www.google.com here im sure they first contact DNS to get the IP add.
There was a problem hiding this comment.
Yes, it does. Generally, all you need is to check host validity once, at the start of your job.
I think that using dns for this purpose appears to be more clear then doing it through socket.connect. Otherwise, Its like using a bicycle when you need a wheel.
| } | ||
|
|
||
| switch (arg[2]) { | ||
| case '--ports': |
There was a problem hiding this comment.
Instead of using imperative switch case which will grow very rapidly if you gonna add more params to your program, it's better to create more universal solution to parse arguments. Maybe something like this (simplified):
function parseArguments(args) {
const parsedArgs = args.slice(2).reduce((acc, arg) => {
if (arg.startsWith('--') && !acc.lastKey) {
acc.lastKey = arg.replace('--', '')
} else if (acc.lastKey) {
acc.result = {...acc.result, [acc.lastKey]: arg}
acc.lastKey = null
} else {
throw new Error(`Unexpected argument '${arg}'`)
}
return acc
}, {result: {}, lastKey: null}).result
if (parsedArgs.lastKey) throw new Error(`Unexpected key '${acc.lastKey}' without value`)
return parsedArgs.result
}There was a problem hiding this comment.
const args = ['node',
'/home/index.js',
'--one',
'two',
'--three',
'four']
parseArguments(args)
// {one: "two", three: "four"}There was a problem hiding this comment.
hehe you gave me the solution, thanks, I will make the changes.
There was a problem hiding this comment.
This was a very challenging function, this reduce is kind of crazy, but I like it and it has a bunch of functionalities. I hope in the future I can use it again :D
There was a problem hiding this comment.
In a real world apps you might be using external package for that. (like yargs) My implementation is very straightforward.
| async function runPorts(host, lowerPort, higherPort) { | ||
| const portList = []; | ||
| for (let i = lowerPort; i <= higherPort; i += 1) { | ||
| /* eslint-disable */ |
There was a problem hiding this comment.
use
/* eslint-disable no-await-in-loop */
lempiy
left a comment
There was a problem hiding this comment.
Last challenge is to fix host validation.

Sniffer TCP UDP Network