haraka / haraka-net-utils

haraka network utilities
https://www.npmjs.com/package/haraka-net-utils
MIT License
2 stars 13 forks source link

STUN timeout fails #84

Closed lnedry closed 4 months ago

lnedry commented 7 months ago

A STUN timeout does not end the test if Stun is not installed and running.

Haraka Haraka.js — Version: 3.0.2
Node v20.11.0
OS Linux mx 5.10.0-27-amd64 #1 SMP Debian 5.10.205-2 (2023-12-31) x86_64 GNU/Linux
openssl OpenSSL 1.1.1w 11 Sep 2023

This is a fresh install of Haraka on Debian 11. Stun is not installed.

With this command, I get four errors # time npm test

  103 passing (8s)
  4 failing

  1) is_local_host
       127.0.0.1:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/etc/haraka/node_modules/haraka-net-utils/test/net_utils.js)
      at listOnTimeout (node:internal/timers:573:17)
      at process.processTimers (node:internal/timers:514:7)

  2) is_local_host
       self ip:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/etc/haraka/node_modules/haraka-net-utils/test/net_utils.js)
      at listOnTimeout (node:internal/timers:573:17)
      at process.processTimers (node:internal/timers:514:7)

  3) get_public_ip
       normal:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/etc/haraka/node_modules/haraka-net-utils/test/net_utils.js)
      at listOnTimeout (node:internal/timers:573:17)
      at process.processTimers (node:internal/timers:514:7)

  4) get_public_ip_async
       normal:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/etc/haraka/node_modules/haraka-net-utils/test/net_utils.js)
      at listOnTimeout (node:internal/timers:573:17)
      at process.processTimers (node:internal/timers:514:7)

After 10 seconds I get three STUN timeouts:

Error: STUN timeout
    at Timeout._onTimeout (/etc/haraka/node_modules/haraka-net-utils/index.js:327:15)
    at listOnTimeout (node:internal/timers:573:17)
    at process.processTimers (node:internal/timers:514:7)
Error: timeout
    at Timeout.<anonymous> (/etc/haraka/node_modules/haraka-net-utils/node_modules/@msimerson/stun/src/net/request.js:181:38)
    at listOnTimeout (node:internal/timers:573:17)
    at process.processTimers (node:internal/timers:514:7)
Error: timeout
    at Timeout.<anonymous> (/etc/haraka/node_modules/haraka-net-utils/node_modules/@msimerson/stun/src/net/request.js:181:38)
    at listOnTimeout (node:internal/timers:573:17)
    at process.processTimers (node:internal/timers:514:7)

After another 60 seconds the test run completes.

real    1m10.865s
user    0m1.801s
sys 0m0.358s

After installing and running stun, the tests run successfully.

msimerson commented 7 months ago

How was it installed? Stun is listed as an optional dependency and typically gets installed.

lnedry commented 7 months ago

Ah, I had to open an outbound port 19302 on the firewall and now the tests work. But if that port is blocked, then the timeout fails as demonstrated.

msimerson commented 7 months ago

So we're good then, and this issue can be closed?

lnedry commented 7 months ago

The original issue still exists. When the 10 second timeout occurs in either the get_public_ip (lines 325-328) or get_public_ip_async (lines 287-290) functions, it returns but the request to the stun server doesn't abort and doesn't timeout until 60 seconds has passed. You can see this issue by blocking port 19302 and running the test suite.

msimerson commented 5 months ago

Please test this patch and see if it does the needful:

diff --git a/index.js b/index.js
index 77955e7..937f14c 100644
--- a/index.js
+++ b/index.js
@@ -287,7 +287,7 @@ exports.get_public_ip_async = async function () {
   }, timeout * 1000)

   // Connect to STUN Server
-  const res = await this.stun.request(get_stun_server())
+  const res = await this.stun.request(get_stun_server(),  { maxTimeout: (timeout - 1) * 1000 })
   this.public_ip = res.getXorAddress().address
   clearTimeout(timer)
   return this.public_ip

@@ -324,12 +323,12 @@ exports.get_public_ip = async function (cb) {
   }, timeout * 1000)

   // Connect to STUN Server
-  nu.stun.request(get_stun_server(), (error, res) => {
+  nu.stun.request(get_stun_server(), { maxTimeout: (timeout - 1) * 1000 }, (error, res) => {
     if (timer) clearTimeout(timer)
     if (error) return cb(error)