From c60913b79608e69215743d3d1ab02202cf370cf0 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:04:28 +0100 Subject: [PATCH] fix: Properly handle timeouts --- bun.lockb | Bin 4066 -> 4066 bytes package.json | 4 +- src/index.ts | 18 +++----- src/routes/port.ts | 24 +++++++++- src/utils/connect-to-address.ts | 75 ++++++++++++++++++-------------- src/utils/timeout.ts | 4 ++ 6 files changed, 76 insertions(+), 49 deletions(-) create mode 100644 src/utils/timeout.ts diff --git a/bun.lockb b/bun.lockb index a4739f5e91a5ea1af86e6d4f284ce23c71a7da35..ec02b3d8a2070cbe6b3670ece4eae2316e6be6e0 100755 GIT binary patch delta 203 zcmaDP|44pq6DRp` z$W`b@EwR%*Iq}5_MyAONIrKL_U{qyxm@<|7n`XDqjjgF)FaI#LS|bpfr_{#wY||IH zjgrb&d)+4-T=>}}4inDe`wF;~HIvkMM=#)_S^J3-w0~fBZ{m;g; zLcecI?1J+RsjL1tCbu#CG-p(6lep>4eM#@Dg5*`6kV{$ { - const port = Number(context.req.param("port")) - const info = getConnInfo(context) - const ipAddress = info.remote.address! - - const result = await connectToAddress(ipAddress, port) - - return context.json({ - isOpen: result.isOpen - }) -}) +app.route( + "/", + portRoute, +) export default app diff --git a/src/routes/port.ts b/src/routes/port.ts index 21f5536..543c790 100644 --- a/src/routes/port.ts +++ b/src/routes/port.ts @@ -7,8 +7,8 @@ import * as IP from "ip" export const portRoute = new Hono(); const schema = z.object({ - ip: z.string().refine(ip => !IP.isPublic(ip), "This IP address is not valid"), - port: z.coerce.number().min(1).max(2**16 - 1), + ip: z.string().refine(ip => IP.isPublic(ip), "This IP address is not valid"), + port: z.string().transform(Number).pipe(z.number().min(1).max(2**16 - 1)), }); portRoute.get("/:port", async context => { @@ -31,3 +31,23 @@ portRoute.get("/:port", async context => { isOpen: result.isOpen }) }); + +portRoute.get("/:ip/:port", async context => { + const rawData = { + ip: context.req.param("ip"), + port: context.req.param("port"), + }; + const parsedData = schema.safeParse(rawData); + + if (!parsedData.success) { + return context.json({ error: parsedData.error }, 401); + } + + const { ip, port } = parsedData.data; + + const result = await connectToAddress(ip, port) + + return context.json({ + isOpen: result.isOpen + }) +}) diff --git a/src/utils/connect-to-address.ts b/src/utils/connect-to-address.ts index 078df85..1434bbc 100644 --- a/src/utils/connect-to-address.ts +++ b/src/utils/connect-to-address.ts @@ -1,43 +1,54 @@ +import * as net from "net" + export interface ConnectionResult { isOpen: boolean } -const TIMEOUT = 5 +const TIMEOUT = 5_000 export default function connectToAddress(address: string, port: number): Promise { return new Promise(async (resolve) => { - const socket = await Bun.connect({ - hostname: address, - port: port, - - socket: { - open(socket) { - socket.end() - resolve({ - isOpen: true - }) - }, - data() { - }, - connectError() { - resolve({ - isOpen: false - }) - }, - error(socket) { - socket.end() - resolve({ - isOpen: false - }) - }, - timeout() { - resolve({ - isOpen: false - }) - }, + const onIsOpen = () => { + if (!socket.destroyed) { + socket.end() + socket.destroy() } - }) - socket.timeout(TIMEOUT) + resolve({ + isOpen: true + }) + } + const onIsClosed = () => { + if (!socket.destroyed) { + socket.end() + socket.destroy() + } + + resolve({ + isOpen: false + }) + } + + const socket = new net.Socket() + + // The `setTimeout` function from a socket does not work when connecting, + // so we need to use a custom timeout function ourselves. + setTimeout(() => { + if (!socket.destroyed) { + socket.end() + socket.destroy() + } + + resolve({ + isOpen: false + }) + }, TIMEOUT) + + socket.on("ready", onIsOpen) + socket.on("close", onIsClosed) + socket.on("error", onIsClosed) + socket.on("timeout", onIsClosed) + + socket.connect(port, address) }) } diff --git a/src/utils/timeout.ts b/src/utils/timeout.ts new file mode 100644 index 0000000..9ec9b47 --- /dev/null +++ b/src/utils/timeout.ts @@ -0,0 +1,4 @@ +export default function timeout(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)) +} +