'socket.io: assure socket joins only one room at a time

I'm working with socket.io 1.3.5. Clients can join rooms by sending a join message. Serverside code:

socket.on('join', function(room) {
  socket.join(room);
});

Now I want to make sure that a client can only be in one room at a time. I want the client to automatically leave the current room if he joins a new one. This is my approach:

function leaveAllRooms(socket) {
    var rooms = socket.adapter.sids[socket.id];
    Object.keys(rooms).forEach(function(room) {
        if (room != socket.id) {
          socket.leave(room);
        }
    });
}

socket.on('join', function(room) {
  leaveAllRooms(socket);
  socket.join(room);
});

Whenever a client want's to join a room, I call leaveAllRooms which calls socket.leave() for all rooms found in socket.adapter.sids[socket.id], except the sockets own room.

This solution seems to be working well, but I'm not sure if it is correct. In another post's comment it is mentioned that io.sockets.manager.roomClients[socket.id] can be used (instead of my socket.adapter.sids[socket.id]). I don't know which one is better. Is there a documentation about this somewhere? I find the docs at socket.io quite sparse.

In addition I wonder if this solution will work with namespaces or even multiple socket.io instances connected via Redis. Any advice?



Solution 1:[1]

If you're really just managing to one room at a time from your join message, then you could do this:

socket.on('join', function(room) {
    if (socket.lastRoom) {
        socket.leave(socket.lastRoom);
        socket.lastRoom = null;
    }
    socket.join(room);
    socket.lastRoom = room;
});

It just stores the last room that it was put in as a property on the socket.

This limits a given socket to only one room at a time as processed by your join message. If a client opens more than one socket, then each socket it opens can be in its own room since you haven't tracked this by an authenticated user id, only by socket. I don't understand your multiple instance/redis question since your requirement was that a given socket was only in one room at a time which this implements (a given socket only exists in one place).


If you wanted to change the requirements and limit one user to one room at a time and you were using multiple servers and the user could open multiple clients, then you'd have to get a lot more complicated, by storing the last room and server instance centrally in redis so you could enforce policy across multiple servers.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1