2
\$\begingroup\$

I'm coding a simple websocket chat app. I was wondering if my code is secure and efficient. I also have a question about the way how I'm sending objects and then checking the type, is there anything better/efficient I can do? Such as making my own events?

Please tell me any improvements I can do.

This is the chat.js (client side script):

I'm most concerned about this line: ws.send(JSON.stringify({type:"connectBoth", senderid:res.receiverid, receiverid:res.senderid}))

There is no direct input into that line, but can't they just open console and go execute that function themselves? With their own parameters they choose, and thus result in a connection with somoene that didn't agree?

let id = document.getElementById("chatid");
function copyID(){
    navigator.clipboard.writeText(id.innerHTML);

    alert("Copied!");
}


(function() {
    const sendBtn = document.getElementById("send");
    const messages = document.getElementById("chatModule");
    const messageBox = document.getElementById("message");
    const friendIDBox = document.getElementById("friend-id");
    const connectBtn = document.getElementById("connect");
    const connStatus = document.getElementById("conn-status");

    let ws;

    

    function showMessage(message, side){
        var newMessage = document.createElement("div");
        if(side == "sender"){
            newMessage.setAttribute("class", "sendermessage");
        }
        else if(side == "receiver"){
            newMessage.setAttribute("class", "receivermessage"); 
        }
        newMessage.textContent = message;
        messages.appendChild(newMessage);
        messageBox.value = '';
    }

    function init(){
        if(ws){
            ws.onerror = ws.onopen = ws.onclose = null;
            ws.close();
        }

        ws = new WebSocket('ws://localhost:8080/?token=2121');
        ws.onopen = () => {
            console.log('Connection opened!')
        }
        // ws.onmessage =  ({ data }) => showMessage(data, "receiver");
        ws.onmessage = object => {
            res = JSON.parse(object.data);
            console.log(res);
            switch(res.type){
                case "id":
                    id.innerText = res.data;
                break;
                case "connectionPrompt":
                    let agree = confirm("Do you want to connect with: " + res.senderid);
                    if(agree){
                        ws.send(JSON.stringify({type:"connectBoth", senderid:res.receiverid, receiverid:res.senderid}))
                        connStatus.innerText = "Connection status: Connected to " + res.senderid;
                    }
                break;
                case "connAccepted":
                    connStatus.innerText = "Connection status: Connected to " + res.senderid;
                break;
                case "msg":
                    showMessage(res.msg, "receiver");
                break;

            }
        } 
        ws.onclose = function(){
            ws = null;
        }
    }

    sendBtn.onclick = () => {
        if(!ws){
            showMessage("No WebSocket connection!");
            return;
        }

        ws.send(JSON.stringify({type:"msg", data:messageBox.value}));
        showMessage(messageBox.value, "sender");
    } 

    connectBtn.onclick = () => {
        ws.send(JSON.stringify({type:"connectRequest", data:friendIDBox.value}));
        connStatus.innerText = "Connection status: Pending..."
        alert("Request sent!");
    }

    

    init();
})();

This is the server.js (server side-script)

const express = require('express');
const { json } = require('express/lib/response');
const http = require('http');
const WebSocket = require('ws');
//Web server socket = wss
const port = 8080;
const server = http.createServer(express);
const wss = new WebSocket.Server({ server });




function heartbeat() {
    this.isAlive = true;
}

function generateID(){
    return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
}

wss.getUniqueID = () => {
    return generateID() + generateID() + generateID();
}
    


wss.on("connection", function connection(ws){
    ws.id = wss.getUniqueID();
    ws.send(JSON.stringify({type:"id", data: ws.id}));
    console.log("New client connected with id: " + ws.id);
    ws.isAlive = true;
    ws.on('pong', heartbeat);
    ws.on("message", function incoming(data, isBinary){
        let message = isBinary ? data : data.toString();
        message = JSON.parse(message);
        console.log(message);
        switch(message.type){
            case "connectRequest":
                wss.clients.forEach(client => {
                    if(client.id == message.data)
                    client.send(JSON.stringify({type:"connectionPrompt", senderid:ws.id, receiverid:message.data }))
                })
                // ws.friendid = message.data;

            break;
            case "connectBoth":
                ws.friendid = message.receiverid;
                wss.clients.forEach(client => {
                    if(client.id == message.receiverid){
                        client.friendid = message.senderid;
                        client.send(JSON.stringify({type:"connAccepted", senderid:message.senderid}))
                    }
                })

            break;
            case "msg":
                wss.clients.forEach(client => {
                    if(client != ws && client.readyState == WebSocket.OPEN){
                        console.log("Client id: " + client.id + " and " + client.friendid);
                        if (client.id == ws.friendid){
                            client.send(JSON.stringify({type:"msg", msg:message.data}));
                        }
                   }
                    
                })
            break;
            
        }
        
        
        
        // const message = isBinary ? data : data.toString();
        // wss.clients.forEach(function each(client){
        //     if(client != ws && client.readyState == WebSocket.OPEN){
        //         client.send(message);
        //     }
        // })
    })
    

})

const interval = setInterval(function ping() {
    wss.clients.forEach(function each(ws) {
      if (ws.isAlive === false) return ws.terminate();
  
      ws.isAlive = false;
      ws.ping();
    });
  }, 1000);
  

  wss.on('close', function close() {
    clearInterval(interval);
    console.log("Connection lost!");
  });
  

server.listen(port, function(){
    console.log('Server is listening on ' + port);
});

Thanks, Kind Regards!

\$\endgroup\$
0

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.