Merge pull request #504 from bigbluebutton/fix-how-we-use-sessionid-to-identify-user

Fix how we use sessionid to identify user
This commit is contained in:
Fred Dixon 2015-02-02 17:56:18 -05:00
commit 078f4f1dae
18 changed files with 66 additions and 90 deletions

View File

@ -2,6 +2,7 @@ apply plugin: 'scala'
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse'
apply plugin: 'idea'
version = '0.9.0'
jar.enabled = true

View File

@ -137,11 +137,14 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter {
if (record == true) {
recorderApplication.createRecordSession(room);
}
String userId = internalUserID;
String sessionId = CONN + userId;
BigBlueButtonSession bbbSession = new BigBlueButtonSession(room, internalUserID, username, role,
voiceBridge, record, externalUserID, muted);
voiceBridge, record, externalUserID, muted, sessionId);
connection.setAttribute(Constants.SESSION, bbbSession);
connection.setAttribute("INTERNAL_USER_ID", internalUserID);
connection.setAttribute("USER_SESSION_ID", sessionId);
String debugInfo = "internalUserID=" + internalUserID + ",username=" + username + ",role=" + role + "," +
",voiceConf=" + voiceBridge + ",room=" + room + ",externalUserid=" + externalUserID;
@ -150,12 +153,11 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter {
bbbGW.initLockSettings(room, locked, lsMap);
String meetingId = bbbSession.getRoom();
String userId = bbbSession.getInternalUserID();
String connType = getConnectionType(Red5.getConnectionLocal().getType());
String userFullname = bbbSession.getUsername();
String connId = Red5.getConnectionLocal().getSessionId();
String sessionId = CONN + connId + "-" + userId;
connInvokerService.addConnection(sessionId, connection);
log.info("User connected: sessionId=[" + sessionId + "], encoding=[" + connType +
@ -176,7 +178,7 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter {
Gson gson = new Gson();
String logStr = gson.toJson(logData);
log.info("User joining bbb-aaps: data={}", logStr);
log.info("User joining bbb-apps: data={}", logStr);
return super.roomConnect(connection, params);
@ -208,7 +210,7 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter {
String userFullname = bbbSession.getUsername();
String connId = Red5.getConnectionLocal().getSessionId();
String sessionId = CONN + connId + "-" + userId;
String sessionId = CONN + userId;
log.info("User disconnected: sessionId=[" + sessionId + "], encoding=[" + connType +
"], meetingId= [" + meetingId + "], userId=[" + userId + "] username=[" + userFullname +"]");
@ -227,7 +229,7 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter {
String logStr = gson.toJson(logData);
log.info("User leaving bbb-apps: data={}", logStr);
connInvokerService.removeConnection(sessionId);
bbbGW.userLeft(bbbSession.getRoom(), getBbbSession().getInternalUserID(), sessionId);
@ -236,7 +238,6 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter {
}
public void validateToken(Map<String, String> msg) {
// String userId = (String) msg.get("userId");
String token = (String) msg.get("authToken");
BigBlueButtonSession bbbSession = (BigBlueButtonSession) Red5.getConnectionLocal().getAttribute(Constants.SESSION);
@ -261,37 +262,7 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter {
log.info("User validate token bbb-apps: data={}", logStr);
bbbGW.validateAuthToken(meetingId, userId, token, meetingId + "/" + userId, sessionId);
}
public void joinMeeting(String userId) {
BigBlueButtonSession bbbSession = getBbbSession();
if (bbbSession != null) {
String userid = bbbSession.getInternalUserID();
String username = bbbSession.getUsername();
String role = bbbSession.getRole();
String meetingId = bbbSession.getRoom();
log.debug(APP + ":joinMeeting - [" + meetingId + "] [" + userid + ", " + username + ", " + role + "]");
String connId = Red5.getConnectionLocal().getSessionId();
String sessionId = CONN + connId + "-" + userId;
Map<String, Object> logData = new HashMap<String, Object>();
logData.put("meetingId", meetingId);
logData.put("connId", connId);
logData.put("userId", userId);
logData.put("sessionId", sessionId);
logData.put("username", username);
logData.put("event", "user_join_bbb_apps");
logData.put("description", "User join BBB Apps.");
Gson gson = new Gson();
String logStr = gson.toJson(logData);
log.info("User join bbb-aaps: data={}", logStr);
bbbGW.userJoin(meetingId, userid, sessionId);
}
}
public void setRecorderApplication(RecorderApplication a) {
recorderApplication = a;
}

View File

@ -28,10 +28,11 @@ public class BigBlueButtonSession {
private final Boolean record;
private final String externalUserID;
private final Boolean startAsMuted;
private final String sessionId;
public BigBlueButtonSession(String room, String internalUserID, String username,
String role, String voiceBridge, Boolean record,
String externalUserID, Boolean startAsMuted){
String externalUserID, Boolean startAsMuted, String sessionId){
this.internalUserID = internalUserID;
this.username = username;
this.role = role;
@ -40,6 +41,7 @@ public class BigBlueButtonSession {
this.record = record;
this.externalUserID = externalUserID;
this.startAsMuted = startAsMuted;
this.sessionId = sessionId;
}
public String getUsername() {
@ -73,4 +75,8 @@ public class BigBlueButtonSession {
public Boolean getStartAsMuted() {
return startAsMuted;
}
public String getSessionId() {
return sessionId;
}
}

View File

@ -26,6 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.IConnection;
import org.red5.server.api.scope.IScope;
@ -40,6 +41,8 @@ import org.slf4j.Logger;
public class ConnectionInvokerService {
private static Logger log = Red5LoggerFactory.getLogger(ConnectionInvokerService.class, "bigbluebutton");
private final String CONN = "RED5-";
private static final int NTHREADS = 1;
private static final Executor exec = Executors.newFixedThreadPool(NTHREADS);
private static final Executor runExec = Executors.newFixedThreadPool(NTHREADS);
@ -75,6 +78,7 @@ public class ConnectionInvokerService {
if (conn == null) {
System.out.println("CONN IS NULL");
}
connections.putIfAbsent(id, conn);
}
@ -150,7 +154,8 @@ public class ConnectionInvokerService {
private void handlDisconnectClientMessage(DisconnectClientMessage msg) {
IScope meetingScope = getScope(msg.getMeetingId());
if (meetingScope != null) {
IConnection conn = getConnection(meetingScope, msg.getUserId());
String sessionId = CONN + msg.getUserId();
IConnection conn = getConnection(meetingScope, sessionId);
if (conn != null) {
if (conn.isConnected()) {
log.info("Disconnecting user=[{}] from meeting=[{}]", msg.getUserId(), msg.getMeetingId());
@ -182,19 +187,26 @@ public class ConnectionInvokerService {
}
private void sendDirectMessage(final DirectClientMessage msg) {
final String sessionId = CONN + msg.getUserID();
Runnable sender = new Runnable() {
public void run() {
IScope meetingScope = getScope(msg.getMeetingID());
if (meetingScope != null) {
IConnection conn = getConnection(meetingScope, msg.getUserID());
IConnection conn = getConnection(meetingScope, sessionId);
if (conn != null) {
if (conn.isConnected()) {
log.debug("Sending message=[" + msg.getMessageName() + "] to [" + sessionId
+ "] session on meeting=[" + msg.getMeetingID() + "]");
List<Object> params = new ArrayList<Object>();
params.add(msg.getMessageName());
params.add(msg.getMessage());
ServiceUtils.invokeOnConnection(conn, "onMessageFromServer", params.toArray());
}
}
} else {
log.info("Cannot send message=[" + msg.getMessageName() + "] to [" + sessionId
+ "] as no such session on meeting=[" + msg.getMeetingID() + "]");
}
}
}
};
@ -219,7 +231,7 @@ public class ConnectionInvokerService {
private IConnection getConnection(IScope scope, String userID) {
Set<IConnection> conns = scope.getClientConnections();
for (IConnection conn : conns) {
String connID = (String) conn.getAttribute("INTERNAL_USER_ID");
String connID = (String) conn.getAttribute("USER_SESSION_ID");
if (connID != null && connID.equals(userID)) {
return conn;
}

View File

@ -59,7 +59,7 @@ public class ParticipantsApplication {
bbbInGW.assignPresenter(room, newPresenterID, newPresenterName, assignedBy);
}
public void getUsers(String meetingID, String requesterID) {
public void getUsers(String meetingID, String requesterID, String sessionId) {
bbbInGW.getUsers(meetingID, requesterID);
}

View File

@ -81,7 +81,6 @@ public class ParticipantsHandler implements IApplication{
@Override
public boolean roomJoin(IClient client, IScope scope) {
registerUser();
return true;
}
@ -93,25 +92,6 @@ public class ParticipantsHandler implements IApplication{
public void roomStop(IScope scope) {
}
public void registerUser() {
log.debug(APP + ":participantJoin - getting userid");
BigBlueButtonSession bbbSession = getBbbSession();
if (bbbSession != null) {
String userid = bbbSession.getInternalUserID();
String username = bbbSession.getUsername();
String role = bbbSession.getRole();
String room = bbbSession.getRoom();
log.debug(APP + ":participantJoin - [" + room + "] [" + userid + ", " + username + ", " + role + "]");
Map<String, Boolean> status = new HashMap<String, Boolean>();
status.put("raiseHand", false);
status.put("presenter", false);
status.put("hasStream", false);
participantsApplication.registerUser(room, userid, username, role, bbbSession.getExternUserID());
}
}
public void setParticipantsApplication(ParticipantsApplication a) {
participantsApplication = a;
}

View File

@ -31,7 +31,8 @@ import org.bigbluebutton.conference.Constants;
public class ParticipantsService {
private static Logger log = Red5LoggerFactory.getLogger( ParticipantsService.class, "bigbluebutton" );
private ParticipantsApplication application;
private final String CONN = "RED5-";
public void assignPresenter(Map<String, String> msg) {
IScope scope = Red5.getConnectionLocal().getScope();
application.assignPresenter(scope.getName(), (String) msg.get("newPresenterID"), (String) msg.get("newPresenterName"), (String) msg.get("assignedBy"));
@ -39,7 +40,9 @@ public class ParticipantsService {
public void getParticipants() {
IScope scope = Red5.getConnectionLocal().getScope();
application.getUsers(scope.getName(), getBbbSession().getInternalUserID());
String connId = Red5.getConnectionLocal().getSessionId();
String sessionId = CONN + connId + "-" + getBbbSession().getInternalUserID();
application.getUsers(scope.getName(), getBbbSession().getInternalUserID(), sessionId);
}
public void userRaiseHand() {

View File

@ -37,7 +37,7 @@ public interface IBigBlueButtonInGW {
void setUserStatus(String meetingID, String userID, String status, Object value);
void getUsers(String meetingID, String requesterID);
void userLeft(String meetingID, String userID, String sessionId);
void userJoin(String meetingID, String userID, String sessionId);
void userJoin(String meetingID, String userID, String authToken);
void getCurrentPresenter(String meetingID, String requesterID);
void assignPresenter(String meetingID, String newPresenterID, String newPresenterName, String assignedBy);
void setRecordingStatus(String meetingId, String userId, Boolean recording);

View File

@ -17,7 +17,7 @@ class BigBlueButtonActor(outGW: MessageOutGateway) extends Actor with LogHelper
case msg: CreateMeeting => handleCreateMeeting(msg)
case msg: DestroyMeeting => handleDestroyMeeting(msg)
case msg: KeepAliveMessage => handleKeepAliveMessage(msg)
case msg: GetAllMeetingsRequest => handleGetAllMeetingsRequest(msg)
case msg: GetAllMeetingsRequest => handleGetAllMeetingsRequest(msg)
case msg: InMessage => handleMeetingMessage(msg)
case _ => // do nothing
}
@ -51,7 +51,7 @@ class BigBlueButtonActor(outGW: MessageOutGateway) extends Actor with LogHelper
msg match {
case vat:ValidateAuthToken => {
logger.info("No meeting [" + vat.meetingID + "] for auth token [" + vat.token + "]")
outGW.send(new ValidateAuthTokenReply(vat.meetingID, vat.userId, vat.token, false, vat.correlationId))
outGW.send(new ValidateAuthTokenReply(vat.meetingID, vat.userId, vat.token, false, vat.correlationId, vat.sessionId))
}
case _ => {
logger.info("No meeting [" + msg.meetingID + "] for message type [" + msg.getClass() + "]")

View File

@ -169,8 +169,8 @@ class BigBlueButtonInGW(bbbGW: BigBlueButtonGateway, presUtil: PreuploadedPresen
bbbGW.accept(new UserLeaving(meetingID, userID, sessionId))
}
def userJoin(meetingID: String, userID: String, sessionId: String):Unit = {
bbbGW.accept(new UserJoining(meetingID, userID, sessionId))
def userJoin(meetingID: String, userID: String, authToken: String):Unit = {
bbbGW.accept(new UserJoining(meetingID, userID, authToken))
}
def assignPresenter(meetingID: String, newPresenterID: String, newPresenterName: String, assignedBy: String):Unit = {

View File

@ -95,7 +95,7 @@ case class RegisterUser(
case class UserJoining(
meetingID: String,
userID: String,
sessionId: String
authToken: String
) extends InMessage
case class UserLeaving(

View File

@ -204,7 +204,7 @@ case class UserJoined(
meetingID: String,
recorded: Boolean,
user:UserVO,
version:String = Versions.V_0_0_1
version:String = Versions.V_0_0_1
) extends IOutMessage
case class UserRaisedHand(

View File

@ -59,7 +59,6 @@ case class Voice(
)
case class UserVO(
sessionId: String,
userID: String,
externUserID: String,
name: String,

View File

@ -15,14 +15,16 @@ trait LayoutApp {
private var viewersOnly = true
def handleGetCurrentLayoutRequest(msg: GetCurrentLayoutRequest) {
outGW.send(new GetCurrentLayoutReply(msg.meetingID, recorded, msg.requesterID, currentLayout, permissions.lockedLayout, setByUser))
outGW.send(new GetCurrentLayoutReply(msg.meetingID, recorded, msg.requesterID,
currentLayout, permissions.lockedLayout, setByUser))
}
def handleLockLayoutRequest(msg: LockLayoutRequest) {
viewersOnly = msg.viewersOnly
lockLayout(msg.lock)
outGW.send(new LockLayoutEvent(msg.meetingID, recorded, msg.setById, msg.lock, affectedUsers))
outGW.send(new LockLayoutEvent(msg.meetingID, recorded,
msg.setById, msg.lock, affectedUsers))
msg.layout foreach {l =>
currentLayout = l
@ -31,7 +33,8 @@ trait LayoutApp {
}
private def broadcastSyncLayout(meetingId: String, setById: String) {
outGW.send(new BroadcastLayoutEvent(meetingId, recorded, setById, currentLayout, permissions.lockedLayout, setByUser, affectedUsers))
outGW.send(new BroadcastLayoutEvent(meetingId, recorded, setById,
currentLayout, permissions.lockedLayout, setByUser, affectedUsers))
}
def handleBroadcastLayoutRequest(msg: BroadcastLayoutRequest) {

View File

@ -79,20 +79,20 @@ trait UsersApp {
val replyTo = meetingID + '/' + msg.userId
//send the reply
outGW.send(new ValidateAuthTokenReply(meetingID, msg.userId, msg.token, true, msg.correlationId))
outGW.send(new ValidateAuthTokenReply(meetingID, msg.userId, msg.token, true, msg.correlationId, msg.sessionId))
//send the list of users in the meeting
outGW.send(new GetUsersReply(meetingID, msg.userId, users.getUsers))
outGW.send(new GetUsersReply(meetingID, msg.userId, users.getUsers, msg.sessionId))
//send chat history
this ! (new GetChatHistoryRequest(meetingID, msg.userId, replyTo))
this ! (new GetChatHistoryRequest(meetingID, msg.userId, msg.userId))
//join the user
handleUserJoin(new UserJoining(meetingID, msg.userId, msg.sessionId))
handleUserJoin(new UserJoining(meetingID, msg.userId, msg.token))
//send the presentation
logger.info("ValidateToken success: mid=[" + meetingID + "] uid=[" + msg.userId + "]")
this ! (new GetPresentationInfo(meetingID, msg.userId, replyTo))
this ! (new GetPresentationInfo(meetingID, msg.userId, msg.userId))
}
case None => {
logger.info("ValidateToken failed: mid=[" + meetingID + "] uid=[" + msg.userId + "]")
@ -272,11 +272,11 @@ trait UsersApp {
}
def handleUserJoin(msg: UserJoining):Unit = {
val regUser = regUsers.get(msg.userID)
val regUser = regUsers.get(msg.authToken)
regUser foreach { ru =>
val vu = new VoiceUser(msg.userID, msg.userID, ru.name, ru.name,
false, false, false, false)
val uvo = new UserVO(msg.sessionId, msg.userID, ru.externId, ru.name,
val uvo = new UserVO(msg.userID, ru.externId, ru.name,
ru.role, raiseHand=false, presenter=false,
hasStream=false, locked=false, webcamStream="",
phoneUser=false, vu, listenOnly=false, permissions)
@ -328,14 +328,14 @@ trait UsersApp {
val sessionId = "PHONE-" + webUserId;
val uvo = new UserVO(sessionId, webUserId, webUserId, msg.voiceUser.callerName,
val uvo = new UserVO(webUserId, webUserId, msg.voiceUser.callerName,
Role.VIEWER, raiseHand=false, presenter=false,
hasStream=false, locked=false, webcamStream="",
phoneUser=true, vu, listenOnly=false, permissions)
users.addUser(uvo)
logger.info("New user joined voice for user [" + uvo.name + "] userid=[" + msg.voiceUser.webUserId + "]")
outGW.send(new UserJoined(meetingID, recorded, uvo))
outGW.send(new UserJoined(meetingID, recorded, uvo, sessionId))
outGW.send(new UserJoinedVoice(meetingID, recorded, voiceBridge, uvo))
if (meetingMuted)

View File

@ -137,10 +137,10 @@ class UsersClientMessageSender(service: ConnectionInvokerService) extends OutMes
val message = new java.util.HashMap[String, Object]()
val gson = new Gson();
message.put("msg", gson.toJson(args))
message.put("msg", gson.toJson(args))
// println("UsersClientMessageSender - handleValidateAuthTokenReply \n" + message.get("msg") + "\n")
val m = new DirectClientMessage(msg.meetingID, msg.requesterId, "validateAuthTokenReply", message);
val m = new DirectClientMessage(msg.meetingID, msg.requesterId, "validateAuthTokenReply", message);
service.sendMessage(m);
}

View File

@ -81,8 +81,9 @@ package org.bigbluebutton.modules.videoconf.business
public function VideoWindowItf() {
super();
accessibilityEnabled = false;
titleBarOverlay.accessibilityEnabled = false;
closeBtn.accessibilityEnabled = false;
if (titleBarOverlay != null)
titleBarOverlay.accessibilityEnabled = false;
closeBtn.accessibilityEnabled = false;
}
public function getWindowType():String {