1

I've written the following function:

  let responses = {}
  let socks = {}
  module.ping = function (port, address) {
    //console.log(`Ping function was called - ${address} ${port}`)
    if (socks[`${address}:${port}`]) {
      //console.log("Using existing socket")
      responses[`${address}:${port}`] = false
      sock = socks[`${address}:${port}`]
      sock.write('PING\n')
      console.log(`Sent PING to ${address} ${port}`)
    }
    else {
      sock = new net.Socket();
      responses[`${address}:${port}`] = false
      sock.connect(port, address, async function() {
        sock.write('PING\n')
        console.log(`Sent PING to ${address} ${port}`)
      });

      // Response listeners
      sock.on('data', function(data) {
        clean_data = data.toString().replace(/\n/g, '').replace(/\r/g, '')
        console.log(`[${sock.remoteAddress}:${sock.remotePort}] Received ${clean_data}`)
          if (clean_data == 'PONG') {
            //console.log(`[${sock.remoteAddress}:${sock.remotePort}] Received PONG`)
            //sock.end()
            //delete socks[`${address}:${port}`]
            responses[`${sock.remoteAddress}:${sock.remotePort}`] = true
          }
        }
      });
      sock.on('error', function(error) { 
        if (sock.remoteAddress) {
          responses[`${sock.remoteAddress}:${sock.remotePort}`] = false
        }
        sock.destroy()
        delete socks[`${address}:${port}`]
      });

      // Add to list of sockets
      if (sock) {
        socks[`${address}:${port}`] = sock 
      }
    }
  }

On the other end, I have a listening TCP server that simple responds with "PONG\n". When I try a single host I get the expected output:

module.ping(1337, 10.0.0.100)
await delay(5000) // Custom function
module.ping(1337, 10.0.0.100)

Sent PING to 10.0.0.100 1337

[10.0.0.100:1337] Received PONG

Sent PING to 10.0.0.100 1337

[10.0.0.100:1337] Received PONG

However when I attempt to hit multiple hosts:

module.ping(1337, 10.0.0.100)
module.ping(1337, 10.0.0.200)
await delay(5000) // Custom function
module.ping(1337, 10.0.0.100)
module.ping(1337, 10.0.0.200)

Sent PING to 10.0.0.100 1337

Sent PING to 10.0.0.200 1337

[10.0.0.200:1337] Received PONG

[10.0.0.200:1337] Received PONG

Sent PING to 10.0.0.100 1337

Sent PING to 10.0.0.200 1337

[10.0.0.200:1337] Received PONG

[10.0.0.200:1337] Received PONG

It seems to me that the event listener for "data" I've added has somehow bound to the incorrect address within my code, however I can't see where. If I add more hosts to the list, the last host with the PING sent is the one that all the PONGs are marked as part of.

0

1 Answer 1

2

For starters, I see no declaration for the sock variable which means it's in some some higher scope and getting wrongly confused or trounced between different asynchronous operations that are both in progress.

Declare that variable locally so each use of it is a separate variable and one async operation won't overwrite the one you were using for another operation. ALL variables, not purposely intended to be higher scoped and shared MUST be declared locally.

I don't know if that is the only problem here, but it IS a problem here. For example, if you call .ping() twice in a row and have to create two new sockets, the second one will overwrite the sock variable before the .connect() succeeds causing you to send the PING to the wrong sock which is exactly what your diagnostic logs show.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @jfriend00! I recall you answering my last poorly worded JS question too, really appreciate it. You're 100% right, the variable is leaking out. Adding a let before definition within the function has scoped it correctly and resolved the issue.
@AndrewWhite - Cool. Glad to help. This one is a well written question. You included all relevant code and very good diagnostic logs and a very specific description of what you observed and what you expected. I wish all the questions posted here had those.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.