diff --git a/.env b/.env index 3b09c69..88c960f 100644 --- a/.env +++ b/.env @@ -1,7 +1,14 @@ ENCRYPTION_SECRET=mySuperSecretKey123 PORT=3000 +<<<<<<< HEAD MYSQL_HOST = localhost MYSQL_USER = guardian MYSQL_PASSWORD = Admin@123 -MYSQL_DATABASE = guardiandb \ No newline at end of file +MYSQL_DATABASE = guardiandb +======= +MYSQL_HOST = +MYSQL_USER = +MYSQL_PASSWORD = +MYSQL_DATABASE = +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 diff --git a/app.js b/app.js index 99823cd..e3cb761 100644 --- a/app.js +++ b/app.js @@ -6,10 +6,14 @@ const userRoutes = require('./routes/userRoutes'); const https = require('https'); const fs = require("fs") +<<<<<<< HEAD const {initWebSocket} = require('./services/webSocket') const { connectDB } = require('./config/database'); connectDB(); +======= +const {initWebSocket} = require('./services/webSocket') +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 const app = express(); const sslOptions = { // key: fs.readFileSync('./certificates/fullchain.pem'), @@ -18,12 +22,18 @@ const sslOptions = { // Create HTTP server (use HTTP for now to avoid SSL issues, in production use HTTPS with valid certificates) const server = require('http').createServer(app); +<<<<<<< HEAD // Initialize WebSocket server initWebSocket(server); console.log('WebSocket server initialized'); connectDB() +======= +// Initialize WebSocket server +initWebSocket(server); +console.log('WebSocket server initialized'); +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 // Middleware to parse JSON bodies app.use(express.json()); // 👈 Add this line @@ -31,7 +41,11 @@ app.use(express.json()); // 👈 Add this line app.use(express.static('public')); // CORS Configuration +<<<<<<< HEAD const allowedOrigins = ['https://guardiancalls.tech4bizsolutions.com','http://localhost:5174', 'https://dashboard.tech4biz.info','http://localhost:5173', 'http://192.168.1.35:5173']; // Replace as needed +======= +const allowedOrigins = ['https://guardiancalls.tech4bizsolutions.com','http://localhost:5174', 'https://yourfrontend.com','http://localhost:5173', 'http://192.168.1.35:5173']; // Replace as needed +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 app.use((req, res, next) => { // Check if the request is for the WebSocket test page @@ -82,4 +96,8 @@ const PORT = process.env.PORT || 3000; server.listen(PORT, () => { console.log(`HTTP server running on port ${PORT}`); console.log(`WebSocket server available at ws://localhost:${PORT}`); -}); \ No newline at end of file +<<<<<<< HEAD +}); +======= +}); +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 diff --git a/certificates/fullchain.pem b/certificates/fullchain.pem new file mode 100644 index 0000000..43f9dc1 --- /dev/null +++ b/certificates/fullchain.pem @@ -0,0 +1,48 @@ +-----BEGIN CERTIFICATE----- +MIIDsjCCAzigAwIBAgISBVXyKhgq+z0CAq8r8xlfVOimMAoGCCqGSM49BAMDMDIx +CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF +NTAeFw0yNTA1MjMwOTU3MjdaFw0yNTA4MjEwOTU3MjZaMC4xLDAqBgNVBAMTI2d1 +YXJkaWFuY2FsbHMudGVjaDRiaXpzb2x1dGlvbnMuY29tMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAEFkj1St8i4vM5I3bTlGcAqsc4YssKgdYV/OAy+3y8hMMPHbUi +zF/BMa42ycDEXtw1geS+bzJVFA7HXrco8oOvjqOCAjAwggIsMA4GA1UdDwEB/wQE +AwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIw +ADAdBgNVHQ4EFgQU9oBKl2iP0cojuMRm98APDaPPynQwHwYDVR0jBBgwFoAUnytf +zzwhT50Et+0rLMTGcIvS1w0wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAChhZo +dHRwOi8vZTUuaS5sZW5jci5vcmcvMC4GA1UdEQQnMCWCI2d1YXJkaWFuY2FsbHMu +dGVjaDRiaXpzb2x1dGlvbnMuY29tMBMGA1UdIAQMMAowCAYGZ4EMAQIBMC0GA1Ud +HwQmMCQwIqAgoB6GHGh0dHA6Ly9lNS5jLmxlbmNyLm9yZy8zOS5jcmwwggEDBgor +BgEEAdZ5AgQCBIH0BIHxAO8AdQDM+w9qhXEJZf6Vm1PO6bJ8IumFXA2XjbapflTA +/kwNsAAAAZb8yRBYAAAEAwBGMEQCIHz+37rvli/z4bySkF6Agh4Y/jC0+y/nfK4f +U8DPeRimAiB8Em8y3E85EYbVFIN0z/IrlzSoCUprLW9fJIqjOTyoRgB2AA3h8jAr +0w3BQGISCepVLvxHdHyx1+kw7w5CHrR+Tqo0AAABlvzJEF0AAAQDAEcwRQIgHkAk +1qxFx/uC6tR9UsXyoCsNsQJebJQobahCGxLq7AcCIQDZ+61TBS1DWMoreCG+CEa0 +HeZDfEdZHGXLPpaiPOSkITAKBggqhkjOPQQDAwNoADBlAjEA49BB3QqaDbT43Pdy +xwSI6Loq5eYJNMekJipVsvu+rSmDZ1KU4AEadpd5wZhQoWKlAjB9nS05qX1Q6Gcg +Fq7D/bA2inv7MF2riCMbfkp1nWRJ0LFcOOHlYbor0wrNAwd9w7c= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEVzCCAj+gAwIBAgIRAIOPbGPOsTmMYgZigxXJ/d4wDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw +WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDELMAkGA1UEAxMCRTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNCzqK +a2GOtu/cX1jnxkJFVKtj9mZhSAouWXW0gQI3ULc/FnncmOyhKJdyIBwsz9V8UiBO +VHhbhBRrwJCuhezAUUE8Wod/Bk3U/mDR+mwt4X2VEIiiCFQPmRpM5uoKrNijgfgw +gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD +ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSfK1/PPCFPnQS37SssxMZw +i9LXDTAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB +AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g +BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu +Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAH3KdNEVCQdqk0LKyuNImTKdRJY1C +2uw2SJajuhqkyGPY8C+zzsufZ+mgnhnq1A2KVQOSykOEnUbx1cy637rBAihx97r+ +bcwbZM6sTDIaEriR/PLk6LKs9Be0uoVxgOKDcpG9svD33J+G9Lcfv1K9luDmSTgG +6XNFIN5vfI5gs/lMPyojEMdIzK9blcl2/1vKxO8WGCcjvsQ1nJ/Pwt8LQZBfOFyV +XP8ubAp/au3dc4EKWG9MO5zcx1qT9+NXRGdVWxGvmBFRAajciMfXME1ZuGmk3/GO +koAM7ZkjZmleyokP1LGzmfJcUd9s7eeu1/9/eg5XlXd/55GtYjAM+C4DG5i7eaNq +cm2F+yxYIPt6cbbtYVNJCGfHWqHEQ4FYStUyFnv8sjyqU8ypgZaNJ9aVcWSICLOI +E1/Qv/7oKsnZCWJ926wU6RqG1OYPGOi1zuABhLw61cuPVDT28nQS/e6z95cJXq0e +K1BcaJ6fJZsmbjRgD5p3mvEf5vdQM7MCEvU0tHbsx2I5mHHJoABHb8KVBgWp/lcX +GWiWaeOyB7RP+OfDtvi2OsapxXiV7vNVs7fMlrRjY1joKaqmmycnBvAq14AEbtyL +sVfOS66B8apkeFX2NY4XPEYV4ZSCe8VHPrdrERk2wILG3T/EGmSIkCYVUMSnjmJd +VQD9F6Na/+zmXCc= +-----END CERTIFICATE----- diff --git a/certificates/privkey.pem b/certificates/privkey.pem new file mode 100644 index 0000000..1b3b098 --- /dev/null +++ b/certificates/privkey.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgH6ulvQnwnXO+vjBV +IW7bkzyG1ZjAGYdpW2PSoK2JYtOhRANCAAQWSPVK3yLi8zkjdtOUZwCqxzhiywqB +1hX84DL7fLyEww8dtSLMX8ExrjbJwMRe3DWB5L5vMlUUDsdetyjyg6+O +-----END PRIVATE KEY----- diff --git a/config/database.js b/config/database.js index 63d2f50..672833f 100644 --- a/config/database.js +++ b/config/database.js @@ -10,7 +10,11 @@ const connectDB = async () => { user: process.env.MYSQL_USER, password: process.env.MYSQL_PASSWORD, database: process.env.MYSQL_DATABASE, +<<<<<<< HEAD port: process.env.MYSQL_PORT || 3306, +======= + port: process.env.PORT || 3306, +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 waitForConnections: true, connectionLimit: 100, queueLimit: 0, @@ -31,4 +35,8 @@ const getPool = () => { return pool; }; +<<<<<<< HEAD module.exports = { connectDB, getPool }; +======= +module.exports = { connectDB, getPool }; +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 diff --git a/controllers/userController.js b/controllers/userController.js index c305087..56af601 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -1,7 +1,11 @@ const { fetchContacts } = require("../services/apiService"); +<<<<<<< HEAD const { sendAlertToUser } = require("../services/webSocket"); const jwt = require("jsonwebtoken"); const {getPool} = require("../config/database") +======= +const { sendAlertToUser } = require("../services/webSocket") +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 const fieldTitleMap = { Hq5fePgYMo1lfrJeSXkr: "call_frequency", @@ -82,6 +86,7 @@ async function getNotifications(req,res){ } +<<<<<<< HEAD async function updateAlerts(req, res) { let id = req.body.id @@ -132,4 +137,7 @@ async function updateAlerts(req, res) { res.status(500).json({ error: 'Internal server error' }); } } -module.exports = { getUserData ,getNotifications,updateAlerts}; \ No newline at end of file +module.exports = { getUserData ,getNotifications,updateAlerts}; +======= +module.exports = { getUserData ,getNotifications}; +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index f187660..97039a5 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -39,6 +39,7 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, +<<<<<<< HEAD "node_modules/aws-ssl-profiles": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", @@ -48,6 +49,8 @@ "node": ">= 6.0.0" } }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "node_modules/axios": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", @@ -64,6 +67,7 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, +<<<<<<< HEAD "node_modules/bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", @@ -73,6 +77,8 @@ "node": "*" } }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -320,6 +326,7 @@ "node": ">=0.4.0" } }, +<<<<<<< HEAD "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -329,6 +336,8 @@ "node": ">=0.10" } }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -588,6 +597,7 @@ "url": "https://github.com/sponsors/ljharb" } }, +<<<<<<< HEAD "node_modules/generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -597,6 +607,8 @@ "is-property": "^1.0.2" } }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -798,12 +810,15 @@ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" }, +<<<<<<< HEAD "node_modules/is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", "license": "MIT" }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -894,6 +909,7 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "license": "MIT" }, +<<<<<<< HEAD "node_modules/long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", @@ -924,6 +940,8 @@ "url": "https://github.com/sponsors/wellwelwel" } }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -1062,6 +1080,7 @@ "node": ">= 0.6" } }, +<<<<<<< HEAD "node_modules/mysql": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", @@ -1139,6 +1158,8 @@ "node": ">=12.0.0" } }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -1416,11 +1437,14 @@ "node": ">= 18" } }, +<<<<<<< HEAD "node_modules/seq-queue": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "node_modules/serve-static": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", @@ -1520,6 +1544,7 @@ "node": ">=10" } }, +<<<<<<< HEAD "node_modules/sqlstring": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", @@ -1529,6 +1554,8 @@ "node": ">= 0.6" } }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", diff --git a/package-lock.json b/package-lock.json index a9552af..5215544 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,8 +18,11 @@ "https": "^1.0.0", "jsonwebtoken": "^9.0.2", "multer": "^2.0.0", +<<<<<<< HEAD "mysql": "^2.18.1", "mysql2": "^3.14.1", +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "ws": "^8.18.2" }, "devDependencies": { @@ -930,6 +933,7 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "license": "MIT" }, +<<<<<<< HEAD "node_modules/long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", @@ -960,6 +964,8 @@ "url": "https://github.com/sponsors/wellwelwel" } }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -2377,6 +2383,7 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, +<<<<<<< HEAD "long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", @@ -2392,6 +2399,8 @@ "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==" }, +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", diff --git a/package.json b/package.json index b0008b5..655e2f6 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,11 @@ "https": "^1.0.0", "jsonwebtoken": "^9.0.2", "multer": "^2.0.0", +<<<<<<< HEAD "mysql": "^2.18.1", "mysql2": "^3.14.1", +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 "ws": "^8.18.2" }, "devDependencies": { diff --git a/routes/userRoutes.js b/routes/userRoutes.js index f76c333..e664151 100644 --- a/routes/userRoutes.js +++ b/routes/userRoutes.js @@ -1,13 +1,20 @@ const express = require('express'); const router = express.Router(); +<<<<<<< HEAD const { getUserData, getNotifications,updateAlerts} = require('../controllers/userController'); +======= +const { getUserData, getNotifications} = require('../controllers/userController'); +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 const multer = require('multer'); const upload = multer(); // No disk storage, just for parsing fields router.post('/data', upload.none(), getUserData); router.post('/notifications',upload.none(),getNotifications) +<<<<<<< HEAD router.post('/acknowledge',upload.none(),updateAlerts) +======= +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 module.exports = router; diff --git a/services/webSocket.js b/services/webSocket.js index 1095cf9..6522eeb 100644 --- a/services/webSocket.js +++ b/services/webSocket.js @@ -1,3 +1,4 @@ +<<<<<<< HEAD // const WebSocket = require('ws'); // const jwt = require('jsonwebtoken'); // const db = require('../config/database'); @@ -238,15 +239,36 @@ async function sendUserAlertHistory(ws, userId) { /** * Initializes the WebSocket server. +======= +const WebSocket = require('ws'); +const jwt = require('jsonwebtoken'); + +// user_id -> websocket mapping +const userSocketMap = new Map(); + +// Keep track of connection attempts to prevent rapid reconnection loops +const connectionAttempts = new WeakMap(); + +/** + * Initializes the WebSocket server. + * @param {https.Server} server - The HTTP/HTTPS server instance from Express. +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 */ function initWebSocket(server) { const wss = new WebSocket.Server({ server, clientTracking: true, +<<<<<<< HEAD +======= + // Consider adding ping/pong for connection health + // clientTracking: true, + // maxPayload: 100 * 1024 * 1024, // 100MB +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 }); console.log('WebSocket server initialized'); +<<<<<<< HEAD wss.on('connection', (ws, req) => { const location = url.parse(req.url, true); const token = location.query?.token; @@ -301,10 +323,39 @@ function initWebSocket(server) { }, 30000); ws.on('pong', () => { ws.isAlive = true; }); +======= + // Handle new connections + wss.on('connection', (ws, req) => { + const clientIp = req.socket.remoteAddress; + // console.log(`New WebSocket connection from ${clientIp}`); + + // Set up ping/pong to detect dead connections + let isAlive = true; + ws.isAlive = true; + + const pingInterval = setInterval(() => { + if (!isAlive) { + console.log('Terminating dead connection'); + return ws.terminate(); + } + + isAlive = false; + try { + ws.ping(() => {}); + } catch (e) { + console.error('Error sending ping:', e); + } + }, 30000); + + ws.on('pong', () => { + isAlive = true; + }); +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 ws.on('message', (message) => { try { const data = JSON.parse(message); +<<<<<<< HEAD if (data.type === 'MESSAGE') { ws.send(JSON.stringify({ type: 'MESSAGE_RECEIVED', @@ -331,10 +382,98 @@ function initWebSocket(server) { console.error('WebSocket error:', error); if (ws.readyState === WebSocket.OPEN) { ws.close(1011, 'Internal server error'); +======= + + // Handle different message types + if (data.type === 'MESSAGE') { + console.log(`Received message: ${data.content}`); + ws.send(JSON.stringify({ + type: 'MESSAGE_RECEIVED', + content: data.content, + timestamp: new Date().toISOString() + })); + return; + } + + // Handle authentication with token + const { token } = data; + + if (!token) { + ws.send(JSON.stringify({ + type: 'ERROR', + error: 'No token provided', + timestamp: new Date().toISOString() + })); + return; + } + + const decoded = jwt.decode(token); // Use jwt.verify() in production + const userId = decoded?.claims?.user_id; + + if (!userId) { + ws.send(JSON.stringify({ + type: 'ERROR', + error: 'Invalid token or missing user_id in claims', + timestamp: new Date().toISOString() + })); + return; + } + + console.log(`Authenticated user: ${userId}`); + + // Store the WebSocket connection with the user ID + userSocketMap.set(userId, ws); + + // Store user ID in the WebSocket object for cleanup + ws.userId = userId; + + ws.send(JSON.stringify({ + type: 'CONNECTED', + message: `Connected as ${userId}`, + timestamp: new Date().toISOString() + })); + + } catch (err) { + console.error('WebSocket message error:', err); + try { + ws.send(JSON.stringify({ + type: 'ERROR', + error: 'Invalid message format or processing error', + timestamp: new Date().toISOString() + })); + } catch (sendErr) { + console.error('Failed to send error message:', sendErr); + } + } + }); + + // Handle connection close + ws.on('close', () => { + // console.log(`WebSocket closed for ${ws.userId || 'unknown user'}`); + if (ws.userId) { + userSocketMap.delete(ws.userId); + } + clearInterval(pingInterval); + }); + + // Handle errors + ws.on('error', (error) => { + console.error('WebSocket error:', error); + if (ws.readyState === WebSocket.OPEN) { + try { + ws.close(1011, 'Internal server error'); + } catch (e) { + // Ignore errors during close + } +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 } }); }); +<<<<<<< HEAD +======= + // Handle server errors +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 wss.on('error', (error) => { console.error('WebSocket server error:', error); }); @@ -343,6 +482,7 @@ function initWebSocket(server) { } /** +<<<<<<< HEAD * Send a real-time alert to a specific user via WebSocket. */ async function sendAlertToUser(userId, alert) { @@ -367,6 +507,15 @@ async function sendAlertToUser(userId, alert) { console.error("Database operation failed:", err); } +======= + * Sends an alert to a user via WebSocket. + * @param {string} userId - The target user ID. + * @param {string|object} alert - The alert message or payload. + * @returns {boolean} - Success/failure. + */ +function sendAlertToUser(userId, alert) { + console.log("socket -- invoked---") +>>>>>>> 3d47f2d539024e036b3db88eb1e020180e656065 const ws = userSocketMap.get(userId); if (ws && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: 'ALERT', payload: alert }));