This commit is contained in:
dive2tech 2026-01-21 10:11:21 -05:00 committed by GitHub
commit c21b843829
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 13 deletions

View File

@ -67,23 +67,47 @@ class RadiusClient {
let attempts = 0; let attempts = 0;
let responseReceived = false; let responseReceived = false;
let timeoutHandle; let timeoutHandle;
let socketClosed = false;
/**
* Safely close socket and clear timeout
* @returns {void}
*/
const cleanup = () => {
if (timeoutHandle) {
clearTimeout(timeoutHandle);
timeoutHandle = null;
}
if (!socketClosed) {
socketClosed = true;
try {
socket.close();
} catch (err) {
// Ignore errors during cleanup
}
}
};
/** /**
* Send RADIUS request with retry logic * Send RADIUS request with retry logic
* @returns {void} * @returns {void}
*/ */
const sendRequest = () => { const sendRequest = () => {
if (responseReceived || socketClosed) {
return;
}
attempts++; attempts++;
socket.send(encodedPacket, 0, encodedPacket.length, this.port, this.host, (err) => { socket.send(encodedPacket, 0, encodedPacket.length, this.port, this.host, (err) => {
if (err) { if (err) {
socket.close(); cleanup();
return reject(new Error(`Failed to send RADIUS request: ${err.message}`)); return reject(new Error(`Failed to send RADIUS request: ${err.message}`));
} }
// Set timeout for this attempt // Set timeout for this attempt
timeoutHandle = setTimeout(() => { timeoutHandle = setTimeout(() => {
if (responseReceived) { if (responseReceived || socketClosed) {
return; return;
} }
@ -92,7 +116,7 @@ class RadiusClient {
sendRequest(); sendRequest();
} else { } else {
// All retries exhausted // All retries exhausted
socket.close(); cleanup();
reject(new Error(`RADIUS request timeout after ${attempts} attempts`)); reject(new Error(`RADIUS request timeout after ${attempts} attempts`));
} }
}, this.timeout); }, this.timeout);
@ -101,23 +125,20 @@ class RadiusClient {
// Handle response // Handle response
socket.on("message", (msg) => { socket.on("message", (msg) => {
if (responseReceived) { if (responseReceived || socketClosed) {
return; return;
} }
responseReceived = true; responseReceived = true;
clearTimeout(timeoutHandle); cleanup();
let response; let response;
try { try {
response = radius.decode({ packet: msg, secret: secret }); response = radius.decode({ packet: msg, secret: secret });
} catch (error) { } catch (error) {
socket.close();
return reject(new Error(`RADIUS response decoding failed: ${error.message}`)); return reject(new Error(`RADIUS response decoding failed: ${error.message}`));
} }
socket.close();
// Map response code to match node-radius-client format // Map response code to match node-radius-client format
const responseCode = response.code; const responseCode = response.code;
@ -140,10 +161,9 @@ class RadiusClient {
// Handle socket errors // Handle socket errors
socket.on("error", (err) => { socket.on("error", (err) => {
if (!responseReceived) { if (!responseReceived && !socketClosed) {
responseReceived = true; responseReceived = true;
clearTimeout(timeoutHandle); cleanup();
socket.close();
reject(new Error(`RADIUS socket error: ${err.message}`)); reject(new Error(`RADIUS socket error: ${err.message}`));
} }
}); });

View File

@ -356,10 +356,20 @@ exports.radius = function (
], ],
}) })
.catch((error) => { .catch((error) => {
// Preserve error stack trace and provide better context
if (error.response?.code) { if (error.response?.code) {
throw Error(error.response.code); const radiusError = new Error(`RADIUS ${error.response.code} from ${hostname}:${port}`);
radiusError.response = error.response;
radiusError.originalError = error;
throw radiusError;
} else { } else {
throw Error(error.message); // Preserve original error message and stack trace
const enhancedError = new Error(
`RADIUS authentication failed for ${hostname}:${port}: ${error.message}`
);
enhancedError.originalError = error;
enhancedError.stack = error.stack || enhancedError.stack;
throw enhancedError;
} }
}); });
}; };