Skip to content
This repository was archived by the owner on Mar 19, 2019. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Mozilla Public License Version 2.0
means any form of the work other than Source Code Form.

1.7. "Larger Work"
means a work that combines Covered Software with other material, in
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.

1.8. "License"
Expand Down
171 changes: 97 additions & 74 deletions loop/routes/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,91 +371,114 @@ module.exports = function (apiRouter, conf, logError, storage, filestorage, auth
return;
}
var channel = req.roomStorageData.channel;
var ttl = roomsConf.participantTTL;
var role = req.user === roomOwnerHmac ? 'moderator' : 'publisher';
var sessionToken = tokBox.getSessionToken(
req.roomStorageData.sessionId,
role,
channel
);
req.roomStorageData.sessionToken = sessionToken;

function next(err) {
if (res.serverError(err)) return;
storage.getRoomParticipants(req.token, function(err,
participants) {

// Look in the config for the current apiKey for this channel
if (tokBox.credentials[channel].apiKey !== req.roomStorageData.apiKey) {
// If the apiKey stored in the roomStorageData is not the same as in the config
// Ask for a new sessionId and store it in the roomStorageData.
tokBox.getSession({channel: channel},
function(err, session, opentok) {
if (res.serverError(err)) return;

// When talking about room participants, we are
// talking about user devices present in the room.
req.roomStorageData.sessionId = session.sessionId;
req.roomStorageData.apiKey = opentok.apiKey;

// In case we are rejoining, we don't want to
// consider this session to already be in the
// room. The otherParticipants filters this
// session device from the participant list so
// that we can rejoin even if we are already
// supposed to be in the roon.
storage.setUserRoomData(req.user, req.token,
req.roomStorageData, renderRoomInformation);
});
} else {
renderRoomInformation();
}

var otherParticipants = participants.filter(function(participant) {
return req.user === undefined || participant.userMac !== req.user;
});
function renderRoomInformation(err) {
if (res.serverError(err)) return;

// Room participants are used by metrics
req.roomParticipantsCount = participants.length;

var roomMaxSize = req.roomStorageData.maxSize;
if (!canJoinRoom(
otherParticipants, roomMaxSize,
req.roomStorageData.roomOwnerHmac,
req.user)) {
sendError(res, 400, errors.ROOM_FULL, "The room is full.");
return;
} else if (requestMaxSize <= otherParticipants.length) {
// You cannot handle the number of actual participants.
sendError(res, 400, errors.CLIENT_REACHED_CAPACITY,
"Too many participants in the room for you to handle.");
return;
}

getUserAccount(storage, req, function(err, acc) {
var ttl = roomsConf.participantTTL;
var role = req.user === roomOwnerHmac ? 'moderator' : 'publisher';
var sessionToken = tokBox.getSessionToken(
req.roomStorageData.sessionId,
role,
channel
);
req.roomStorageData.sessionToken = sessionToken;

function next(err) {
if (res.serverError(err)) return;
storage.getRoomParticipants(req.token, function(err,
participants) {
if (res.serverError(err)) return;
encryptAccountName(req.token, acc, function(account) {
req.roomConnectionId = uuid.v4();
storage.addRoomParticipant(req.token, participantHmac, {
id: req.roomConnectionId,
displayName: req.body.displayName,
clientMaxSize: requestMaxSize,
userMac: req.user,
account: account
}, ttl, function(err) {
if (res.serverError(err)) return;

// A participant was just added.
req.roomParticipantsCount++;

emitRoomEvent(req.token,

// When talking about room participants, we are
// talking about user devices present in the room.

// In case we are rejoining, we don't want to
// consider this session to already be in the
// room. The otherParticipants filters this
// session device from the participant list so
// that we can rejoin even if we are already
// supposed to be in the roon.

var otherParticipants = participants.filter(function(participant) {
return req.user === undefined || participant.userMac !== req.user;
});

// Room participants are used by metrics
req.roomParticipantsCount = participants.length;

var roomMaxSize = req.roomStorageData.maxSize;
if (!canJoinRoom(
otherParticipants, roomMaxSize,
req.roomStorageData.roomOwnerHmac,
"join",
function(err) {
if (res.serverError(err)) return;
res.status(200).json({
apiKey: req.roomStorageData.apiKey,
sessionId: req.roomStorageData.sessionId,
sessionToken: sessionToken,
expires: ttl
req.user)) {
sendError(res, 400, errors.ROOM_FULL, "The room is full.");
return;
} else if (requestMaxSize <= otherParticipants.length) {
// You cannot handle the number of actual participants.
sendError(res, 400, errors.CLIENT_REACHED_CAPACITY,
"Too many participants in the room for you to handle.");
return;
}

getUserAccount(storage, req, function(err, acc) {
if (res.serverError(err)) return;
encryptAccountName(req.token, acc, function(account) {
req.roomConnectionId = uuid.v4();
storage.addRoomParticipant(req.token, participantHmac, {
id: req.roomConnectionId,
displayName: req.body.displayName,
clientMaxSize: requestMaxSize,
userMac: req.user,
account: account
}, ttl, function(err) {
if (res.serverError(err)) return;

// A participant was just added.
req.roomParticipantsCount++;

emitRoomEvent(req.token,
req.roomStorageData.roomOwnerHmac,
"join",
function(err) {
if (res.serverError(err)) return;
res.status(200).json({
apiKey: req.roomStorageData.apiKey,
sessionId: req.roomStorageData.sessionId,
sessionToken: sessionToken,
expires: ttl
});
});
});
});
});
});
});
});
}
if (participantHmac === undefined) {
participantHmac = hmac(sessionToken, conf.get('userMacSecret'));
storage.setRoomAccessToken(req.token, participantHmac, ttl, next);
return;
});
}
if (participantHmac === undefined) {
participantHmac = hmac(sessionToken, conf.get('userMacSecret'));
storage.setRoomAccessToken(req.token, participantHmac, ttl, next);
return;
}
next();
}
next();
});
},
handleRefresh: function(req, res) {
Expand Down
35 changes: 35 additions & 0 deletions test/rooms_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,41 @@ describe("/rooms", function() {
});
});
});

it("should refresh the sessionId in case it is obsolete.", function(done) {
createRoom(hawkCredentials).end(function(err, res) {
if (err) throw err;
var roomToken = res.body.roomToken;

storage.getRoomData(roomToken, function(err, roomData) {
if (err) throw err;
// Update apiKey with other credentials
roomData.apiKey = "old api key";
roomData.sessionId = "old sessionId";
storage.setUserRoomData(userHmac, roomToken, roomData, function(err) {
if (err) throw err;
joinRoom(hawkCredentials, roomToken, {
action: "join",
clientMaxSize: 10,
displayName: "Natim"
}).end(function(err, res) {
if (err) throw err;
expect(res.body).to.eql({
"apiKey": tokBox._opentok.default.apiKey,
"expires": conf.get("rooms").participantTTL,
"sessionId": sessionId,
"sessionToken": sessionToken
});
storage.getRoomParticipants(roomToken, function(err, participants) {
if (err) throw err;
expect(participants).to.length(1);
done();
});
});
});
});
});
});
});

describe("Handle 'refresh'", function() {
Expand Down