3
\$\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

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.