From 402ce734b3608c391a4a11b6875d7c2acb8989a9 Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Thu, 6 Mar 2025 19:37:07 -0600 Subject: [PATCH] feat(tcpserver): added in the intial tcpServer startup --- server/index.ts | 2 + .../services/tcpServer/route/restartServer.ts | 48 +++++++++++++ .../services/tcpServer/route/startServer.ts | 46 ++++++++++++ server/services/tcpServer/route/stopServer.ts | 46 ++++++++++++ server/services/tcpServer/tcpServer.ts | 70 +++++++++++++++++++ 5 files changed, 212 insertions(+) create mode 100644 server/services/tcpServer/route/restartServer.ts create mode 100644 server/services/tcpServer/route/startServer.ts create mode 100644 server/services/tcpServer/route/stopServer.ts create mode 100644 server/services/tcpServer/tcpServer.ts diff --git a/server/index.ts b/server/index.ts index f695686..574eb97 100644 --- a/server/index.ts +++ b/server/index.ts @@ -9,6 +9,7 @@ import {log} from "./services/logger/logger.js"; import scalar from "./services/general/route/scalar.js"; import system from "./services/server/systemServer.js"; import auth from "./services/auth/authService.js"; +import tcpServer from "./services/tcpServer/tcpServer.js"; const allowedOrigins = ["http://localhost:3000", "http://localhost:4000", "http://localhost:5173"]; const app = new OpenAPIHono(); @@ -40,6 +41,7 @@ const routes = [ auth, // apiHits, system, + tcpServer, ] as const; const appRoutes = routes.forEach((route) => { diff --git a/server/services/tcpServer/route/restartServer.ts b/server/services/tcpServer/route/restartServer.ts new file mode 100644 index 0000000..93d12f4 --- /dev/null +++ b/server/services/tcpServer/route/restartServer.ts @@ -0,0 +1,48 @@ +import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; +import {authMiddleware} from "../../auth/middleware/authMiddleware.js"; +import {apiHit} from "../../../globalUtils/apiHits.js"; +import {startTCPServer, stopTCPServer} from "../tcpServer.js"; + +const app = new OpenAPIHono(); + +const responseSchema = z.object({ + success: z.boolean().openapi({example: true}), + message: z.string().optional().openapi({example: "user access"}), +}); + +app.openapi( + createRoute({ + tags: ["Server:TCP"], + summary: "Restarts the tcp server up", + method: "get", + path: "/", + middleware: authMiddleware, + description: "Restarts the tcs server with a delay to allow for the entire system to stop and start back up.", + responses: { + 200: { + content: {"application/json": {schema: responseSchema}}, + description: "Succefull restart", + }, + 400: { + content: {"application/json": {schema: responseSchema}}, + description: "Failed to restart server", + }, + }, + }), + async (c) => { + apiHit(c, {endpoint: "api/tcpServer/restart"}); + + try { + const tcpStopServer = stopTCPServer(); + await new Promise((resolve) => setTimeout(resolve, 5000)); + const tcpServer = startTCPServer(); + //return apiReturn(c, true, access?.message, access?.data, 200); + return c.json({success: tcpServer.success, message: tcpServer.message}, 200); + } catch (error) { + console.log(error); + //return apiReturn(c, false, "Error in setting the user access", error, 400); + return c.json({success: false, message: "Error in setting the user access", data: error}, 400); + } + } +); +export default app; diff --git a/server/services/tcpServer/route/startServer.ts b/server/services/tcpServer/route/startServer.ts new file mode 100644 index 0000000..07fd98e --- /dev/null +++ b/server/services/tcpServer/route/startServer.ts @@ -0,0 +1,46 @@ +import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; +import {authMiddleware} from "../../auth/middleware/authMiddleware.js"; +import {apiHit} from "../../../globalUtils/apiHits.js"; +import {startTCPServer} from "../tcpServer.js"; + +const app = new OpenAPIHono(); + +const responseSchema = z.object({ + success: z.boolean().openapi({example: true}), + message: z.string().optional().openapi({example: "user access"}), +}); + +app.openapi( + createRoute({ + tags: ["Server:TCP"], + summary: "Starts the tcp server up", + method: "get", + path: "/", + middleware: authMiddleware, + description: "Starts the tcpServer, must be min an admin to start up", + responses: { + 200: { + content: {"application/json": {schema: responseSchema}}, + description: "restarred", + }, + 400: { + content: {"application/json": {schema: responseSchema}}, + description: "Failed start", + }, + }, + }), + async (c) => { + apiHit(c, {endpoint: "api/tcpServer/start"}); + + try { + const tcpServer = startTCPServer(); + //return apiReturn(c, true, access?.message, access?.data, 200); + return c.json({success: tcpServer.success, message: tcpServer.message}, 200); + } catch (error) { + console.log(error); + //return apiReturn(c, false, "Error in setting the user access", error, 400); + return c.json({success: false, message: "Error in setting the user access", data: error}, 400); + } + } +); +export default app; diff --git a/server/services/tcpServer/route/stopServer.ts b/server/services/tcpServer/route/stopServer.ts new file mode 100644 index 0000000..15d96ee --- /dev/null +++ b/server/services/tcpServer/route/stopServer.ts @@ -0,0 +1,46 @@ +import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; +import {authMiddleware} from "../../auth/middleware/authMiddleware.js"; +import {apiHit} from "../../../globalUtils/apiHits.js"; +import {stopTCPServer} from "../tcpServer.js"; + +const app = new OpenAPIHono(); + +const responseSchema = z.object({ + success: z.boolean().openapi({example: true}), + message: z.string().optional().openapi({example: "user access"}), +}); + +app.openapi( + createRoute({ + tags: ["Server:TCP"], + summary: "Stops the tcp server up", + method: "get", + path: "/", + middleware: authMiddleware, + description: "Stops the tcpServer, must be min an admin to start up", + responses: { + 200: { + content: {"application/json": {schema: responseSchema}}, + description: "stopped", + }, + 400: { + content: {"application/json": {schema: responseSchema}}, + description: "Failed to stop", + }, + }, + }), + async (c) => { + apiHit(c, {endpoint: "api/tcpServer/stop"}); + + try { + const tcpServer = stopTCPServer(); + //return apiReturn(c, true, access?.message, access?.data, 200); + return c.json({success: tcpServer.success, message: tcpServer.message}, 200); + } catch (error) { + console.log(error); + //return apiReturn(c, false, "Error in setting the user access", error, 400); + return c.json({success: false, message: "Error in setting the user access", data: error}, 400); + } + } +); +export default app; diff --git a/server/services/tcpServer/tcpServer.ts b/server/services/tcpServer/tcpServer.ts new file mode 100644 index 0000000..6bca1c0 --- /dev/null +++ b/server/services/tcpServer/tcpServer.ts @@ -0,0 +1,70 @@ +import net from "net"; +import {OpenAPIHono} from "@hono/zod-openapi"; +import {log} from "../logger/logger.js"; + +import startTCP from "./route/startServer.js"; +import stopTCP from "./route/stopServer.js"; +import restartTCP from "./route/restartServer.js"; +import {db} from "../../../database/dbclient.js"; +import {settings} from "../../../database/schema/settings.js"; +import {eq} from "drizzle-orm"; + +let tcpServer: net.Server; +let tcpSockets: Set = new Set(); +let isServerRunning = false; + +const tcpPort = (await db.select().from(settings).where(eq(settings.name, "tcpPort"))) || 2222; +const app = new OpenAPIHono(); + +export const startTCPServer = () => { + if (isServerRunning) return {success: false, message: "Server is already running"}; + + tcpServer = net.createServer((socket) => { + console.log("Client connected"); + + tcpSockets.add(socket); + socket.on("data", (data: Buffer) => { + console.log("Received:", data.toString()); + socket.write("Message received"); + }); + + socket.on("end", () => { + console.log("Client disconnected"); + tcpSockets.delete(socket); + }); + + socket.on("error", (err: Error) => { + console.error("Socket error:", err); + tcpSockets.delete(socket); + }); + }); + + tcpServer.listen(tcpPort[0].value, () => { + log.info(`TCP Server listening on port ${tcpPort[0].value}`); + }); + + isServerRunning = true; + return {success: true, message: "TCP Server started"}; +}; + +// Function to stop the TCP server +export const stopTCPServer = () => { + if (!isServerRunning) return {success: false, message: "Server is not running"}; + for (const socket of tcpSockets) { + socket.destroy(); + } + tcpSockets.clear(); + tcpServer.close(() => { + console.log("TCP Server stopped"); + }); + isServerRunning = false; + return {success: true, message: "TCP Server stopped"}; +}; + +app.route("/tcpServer/start", startTCP); +app.route("/tcpServer/stop", stopTCP); +app.route("/tcpServer/restart", restartTCP); + +// start the server after on system start up +startTCPServer(); +export default app;