-
Notifications
You must be signed in to change notification settings - Fork 14
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
Chikus sniffer revision #12
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
socket has built-in api for timeout https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks!
var timeout = 300; | ||
|
||
function check(host, port, callback) { | ||
var socket = Net.createConnection(port, host); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try to wrap this function in promise and print to console from caller function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In progress
} | ||
|
||
function run_ports(){ | ||
check(host,lower_port, function next_check(result) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned above try to use Promises chaining instead of callbacks with recursion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, but can you tell me more about why this is better??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, and thanks
|
||
function run_ports(){ | ||
check(host,lower_port, function next_check(result) { | ||
if (lower_port == higher_port) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its better to always use ===
to prevent assertion bugs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, Thanks!
}) | ||
}; | ||
|
||
switch (process.argv[2]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use global instructions in your code - wrap them into main
function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, and can you tell me why avoid to use them? thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double self-referencing (check, next_check) is not obvious and a bit dangerous code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const [lower_port, higher_port] = process.argv[3].split('-');
Also check for errors (string with no '-', non-number values)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
@Chikus great job so far! Please check code quality guidelines and fix the style of your code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use reject
for error handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
throw new Error('Ports no defined \n'); | ||
} | ||
|
||
function checkHost(host) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, Done
|
||
function checkHost(host) { | ||
if (host) { | ||
const domains = host.split('.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use dns
node package to validate domain
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool and Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const args = ['node',
'/home/index.js',
'--one',
'two',
'--three',
'four']
parseArguments(args)
// {one: "two", three: "four"}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hehe you gave me the solution, thanks, I will make the changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use
/* eslint-disable no-await-in-loop */
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last challenge is to fix host validation.
Sniffer TCP UDP Network