How do i make my chat message private? - javascript

Now my chat is working but it works like a group message as a third party will be able to see the messages. I want to make it private between two users so that when a third user log in, they will not be able to see the other users talking.
var io = socket(server);
io.on("connection", function(socket){
console.log("made socket connection", socket.id);
socket.on("chat", function(data){
var messages = {
session: data.session,
message: data.message,
sender: data.handle,
};
MsgModel.create(messages);
io.sockets.emit("chat", data);
});
socket.on("typing", function(data){
socket.broadcast.emit("typing", data);
});
});

Emit a join event from client whenever a new client joins with their userid as data. Then on server side, you can use this join event to add user to a room with its userid.
io.on('connection', function(socket){
socket.on("join", function(data){
socket.join(data.userId)
})
})
Now you have rooms with every userid and if you want to send some specific user something, you can emit to that room,
io.to(userid).emit(data)

Related

Vue & Sockets: Handling sending messages back and forth

I have a simple implementation, or an attempt at one, of a messaging system just to show an alert of a message to different users. I'm using https://www.npmjs.com/package/vue-socket.io Vue Socket Io but it's just a socket.io. I am attempting to have the client subscribe to an event in mounted. The name is based on their userID. The problem is that my implementation below doesn't work to show the alerts. I can see the event being subscribed to in mount and I can see sending message console log in the server so I know that is getting fired but I don't see the alert being triggered by the emit(Chat_....
server:
io.on('connection', function(socket) {
socket.on('sendMessage', function (data) {
console.log("Sending message to" + data.user);
socket.emit(`CHAT_${data.user}`, data.msg)
});
});
client:
On the client, the userIDSelf is a user ID that is passed in as a prop. It's the User's logged in ID and in mounted, they automatically subscribe to the a chat channel with their userid appended to it, like a custom channel.
mounted() {
this.sockets.subscribe(`CHAT_${this.userIDSelf}`, (data) => {
alert(data)
});
},
there is a function sendMessage that takes the values from 2 inputs (not seen) in the template. You have to enter a user ID on who you want the message sent to and then another input with the actual message. These are sent over to the backend server listed above.
methods: {
sendMessage() {
this.$socket.emit('sendMessage', {user: this.userIDReceiver, msg: this.message})
},
}
I see a logical problem here. In your server code
io.on('connection', function(socket) {
socket.on('sendMessage', function (data) {
console.log("Sending message to" + data.user);
socket.emit(`CHAT_${data.user}`, data.msg)
});
});
the socket (User 123) which emitted sendMessage event to the server, will eventually also be the socket which will receive the emitted CHAT_456 event from the server. But User 123 socket only listens to CHAT_123 events. The socket is sending itself a message but doesn't receive it.
Possible Solutions
A - the room approach
Once a socket connects on the server, throw it in a room based on it's user id. This requires sending the userid to the server during connection, e.g. with a query parameter. In the client just add a token query parameter to the connection string like
const io = require('socket.io-client');
const socket = io("https://server-domain.com/?token=" + userid);
and through the connecting socket in a room (join) on the server side like
io.on('connection', function(socket) {
const userid = socket.handshake.query.token;
socket.join(userid);
});
then your socket sendMessage would work like this
/* ... server side */
socket.on('sendMessage', function (data) {
console.log("Sending message to" + data.user);
io.to(data.user).emit('chatMessage', data.msg);
});
B - the keep reference to the socket approach
Internally every socket has a socket id. Normally these are not exposed the user/clients. However you do have a unique user id. So let's keep a user id / socket instance - relation on the server side, so you can get a reference to the socket object for each corresponding user, using the user id.
The most basic example for it would be a in-memory store on the server side
let socketRefs = {};
io.on('connection', function(socket) {
const userid = socket.handshake.query.token;
socketRefs[userid] = socket;
});
then your socket sendMessage would work like this
/* ... server side */
socket.on('sendMessage', function (data) {
console.log("Sending message to" + data.user);
let targetSocket = socketRefs[data.user];
targetSocket.emit('chatMessage', data.msg);
});

problem in authenticated rooms in socket.io

I want to create rooms for all private chats between two connected users. I'm not getting the point how do users join the room securely.
// client side code
var socket = io.connect();
socket
.emit('Join-Room',"{\"username\": \"myusername\", \"password\" : \"mypassword\"}");
// server side code
io.sockets.on('connection', function(socket) {
socket.on('Join-Room', function(userdata) {
connection.auth(userdata,function(success){
if(success){
socket.join(username);
}
})
});
});
The problem is when the client emits a request even to join a room the credential data is received by everyone in the namespace?
What should I change to make this secure?

How to create dynamic socket rooms using socket.io

I want to implement multiple chat using socket.io can, iwas able to implement one to one chat using one socket.room but i want to create multiple socket rooms to chat with multiple people parallel
below is the example i got in git but i was not able to understand that how it will work for multiple chat can any one explain
Server side
io = socketio.listen(server);
// handle incoming connections from clients
io.sockets.on('connection', function(socket) {
// once a client has connected, we expect to get a ping from them
saying what room they want to join
socket.on('room', function(room) {
socket.join(room);
});
});
// now, it's easy to send a message to just the clients in a given
room
room = "abc123";
io.sockets.in(room).emit('message', 'what is going on, party
people?');
// this message will NOT go to the client defined above
io.sockets.in('foobar').emit('message', 'anyone in this room yet?');
Client side
// set-up a connection between the client and the server
var socket = io.connect();
// let's assume that the client page, once rendered, knows what room
it wants to join
var room = "abc123";
socket.on('connect', function() {
// Connected, let's sign-up for to receive messages for this room
socket.emit('room', room);
});
socket.on('message', function(data) {
console.log('Incoming message:', data);
});
Imagine a user with multiple Chat Room to choose. When he click on a specific room he will get the information of it : in this example ChatRoom1.
The client socket (belonging to the user who has click on this room) has first to join this room
→ so that's why we have :
socket.emit(room, ChatRoom1)
// on the other part the server side will add the socket id of this client to this room :
socket.on('room', function(room) {
socket.join(room);
});
Now if you want to emit a message to all socket belonging to a specific room you use this command on the server part:
io.sockets.in(ChatRoom1).emit('message', 'what is going on, party
people?');
→ in fact this command just send a message to all socket who is belonging to ChatRoom1
→ Basically a Room is just an array of socketId
SO now on the client side you have this :
socket.on('message', function(data) {
console.log('Incoming message:', data);
});
this is just a listener, and you will get in console log :
Incoming message: what is going on, party people?
As you soon you enter in a chatRoom your socket join a room and will listen for each event until you ask the socket to leave the room
So now you can imagine that in your message you have your Id , Your Room ID and your content, when you send it the server will know where to send it.
Example:
message: {
content: 'blabla',
user: me,
date: now,
RoomId: ChatRoom1
}
On the client side each time a user send a message:
socket.emit('sendMessage', message)
On the server side:
socket.on('sendMessage', function(message){
io.sockets.in(message.RoomId).emit('message', message);
})

Forward all messages to socket.io room

If the client emits a message to a room, how can I get that message sent to all other clients in the room?
Currently on the server I have to do:
io.on('connection', function (socket) {
socket.on('join', function (room) {
socket.join(room);
socket.on('food.create', function (foods) {
socket.broadcast.to(room).emit('food.create', foods);
});
socket.on('food.update', function (foods) {
socket.broadcast.to(room).emit('food.update', foods);
});
socket.on('food.remove', function (foods) {
socket.broadcast.to(room).emit('food.remove', foods);
});
});
});
io.listen(3000);
Which is fine now there's only 3 messages, but when I add more it's going to get long. Does socket.io provide a way of automatically forward all messages form one client to all the other clients in that room?
This is the example off the socket.io docs page that shows how to use events and key:value sets for data:
var io = require('socket.io')();
io.on('connection', function(socket){
socket.emit('an event', { some: 'data' });
});
Why not use this construct to pass the messages around? Put your data in the data object along with what you want the respective client to do with that data as a key:value set. Something like this:
io.to('your_room').emit('food', { todo: 'delete', name: 'macaroni' });
});
The server can then simply broadcast that event to all other clients in the room. That way you don't have to filter messages on the server at all.
The other clients then receive the message and do whatever you want based on the data.todo and data.name values.

Socket.IO clients to receive offline messages when coming back

Environment:
Nodejs+Socketio
Problem:
client A and client B both connect to server;
client B is offline;
client A sends a message to client B(client B still offline);
client B connect to server again;
[Problem] client B can't receive the message from A;
Server Code
var clients = {};
io.sockets.on('connection', function (socket) {
socket.on('online', function (data) {
if (!clients[data.username]) {
clients[data.username] = socket;
}
io.sockets.emit('message', data.user + 'online now');
});
socket.on('say', function (data) {
if (data.to == 'all') {
io.sockets.emit('message', data.message);
} else { //to specific client
clients[data.to].emit('message', data.message);
}
});
});
Description
client B connected to server at one place first.During the period of client B's offline, client A sent messages to client B. Then client B connect to server at another place again, and client B needs to receive those message from client A. How to make it work?
The amount of code I would have to write would be fairly large to create a solution if I consider which db and it's config, and client. You basically have to persist your messages in a database. As messages come in you would have to write to your conversation object (or whatever is representing the chat messages between clients).
socket.on('say', function (data) {
// pseudo code to save conversation
// var conversation = db.getConversation();
// conversation.addMessage(data.message);
// conversation.save();
if (data.to == 'all') {
io.sockets.emit('message', data.message);
} else { //to specific client
clients[data.to].emit('message', data.message);
}
});
Then you would have to get all messages from the database when a client joins.
socket.on('online', function (data) {
if (!clients[data.username]) {
clients[data.username] = socket;
}
// pseudo code to get messages and display to user on first load
// var conversation = db.getConversation();
// var messages = conversation.getLast10Messages();
// messages.forEach(function(message) {
// clients[data.username].emit('message', message);
// });
io.sockets.emit('message', data.user + 'online now');
});
use message queue like RabbitMQ. whenever a message comes from socket write to receiver's queue and when the receiver joins he will pick it from the queue.
You can specify a unique id as username to every user , save it at the server side, or use username, you also have client id(socket id), then save them in an object, now for every user you have an object that contains (username or unique id ) and socket id, now its easy to save messages when user is offline and then send it to user.
Before emitting every event, you can search for socket id in the connected sockets object of socket.if socket id exists, you can emit, else , you still have username, and you can save messages in database by username.
Remember that, you must send receiver object info(username or unique id , and socket id) in every emitting from the client

Categories

Resources