Skip to content

Commit

Permalink
- start implementing user inactivity timer
Browse files Browse the repository at this point in the history
  • Loading branch information
ritzalam committed Apr 6, 2018
1 parent 4052922 commit 39284f1
Show file tree
Hide file tree
Showing 21 changed files with 258 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 21,7 @@ trait SystemConfiguration {
lazy val red5DeskShareIP = Try(config.getString("red5.deskshareip")).getOrElse("127.0.0.1")
lazy val red5DeskShareApp = Try(config.getString("red5.deskshareapp")).getOrElse("")

lazy val inactivityDeadline = Try(config.getInt("inactivity.deadline")).getOrElse(2 * 3600) // 2 hours
lazy val userInactivityTimeout = Try(config.getInt("inactivity.timeout")).getOrElse(2 * 3600) // 2 hours
lazy val inactivityTimeLeft = Try(config.getInt("inactivity.timeLeft")).getOrElse(5 * 60) // 5 minutes

lazy val expireLastUserLeft = Try(config.getInt("expire.lastUserLeft")).getOrElse(60) // 1 minute
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 1,17 @@
package org.bigbluebutton.core.apps.users

import org.bigbluebutton.common2.msgs.UserInactivityAuditResponseMsg
import org.bigbluebutton.core.models.Users2x
import org.bigbluebutton.core.running.MeetingActor

trait UserInactivityAuditResponseMsgHdlr {
this: MeetingActor =>

def handleUserInactivityAuditResponseMsg(msg: UserInactivityAuditResponseMsg):Unit = {
for {
user <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId)
} yield {
Users2x.updateInactivityResponse(liveMeeting.users2x, user)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 26,12 @@ object Users2x {
users.toVector.filter(u => !u.presenter)
}

def updateInactivityResponse(users: Users2x, u: UserState): UserState = {
val newUserState = modify(u)(_.inactivityResponseOn).setTo(System.currentTimeMillis())
users.save(newUserState)
newUserState
}

def changeRole(users: Users2x, u: UserState, newRole: String): UserState = {
val newUserState = modify(u)(_.role).setTo(newRole).modify(_.roleChangedOn).setTo(System.currentTimeMillis())
users.save(newUserState)
Expand Down Expand Up @@ -204,7 210,9 @@ case class OldPresenter(userId: String, changedPresenterOn: Long)

case class UserState(intId: String, extId: String, name: String, role: String,
guest: Boolean, authed: Boolean, guestStatus: String, emoji: String, locked: Boolean,
presenter: Boolean, avatar: String, roleChangedOn: Long = System.currentTimeMillis())
presenter: Boolean, avatar: String,
roleChangedOn: Long = System.currentTimeMillis(),
inactivityResponseOn: Long = 0L)

case class UserIdAndName(id: String, name: String)

Expand Down Expand Up @@ -232,4 240,5 @@ object EjectReasonCode {
val EJECT_USER = "user_requested_eject_reason"
val SYSTEM_EJECT_USER = "system_requested_eject_reason"
val VALIDATE_TOKEN = "validate_token_failed_eject_reason"
val USER_INACTIVITY = "user_inactivity_eject_reason"
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 94,8 @@ class ReceivedJsonMsgHandlerActor(
routeGenericMsg[RemoveUserFromPresenterGroupCmdMsg](envelope, jsonNode)
case GetPresenterGroupReqMsg.NAME =>
routeGenericMsg[GetPresenterGroupReqMsg](envelope, jsonNode)
case UserInactivityAuditResponseMsg.NAME =>
routeGenericMsg[UserInactivityAuditResponseMsg](envelope, jsonNode)

// Poll
case StartCustomPollReqMsg.NAME =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 34,7 @@ import scala.concurrent.duration._
import org.bigbluebutton.core.apps.layout.LayoutApp2x
import org.bigbluebutton.core.apps.meeting.{ SyncGetMeetingInfoRespMsgHdlr, ValidateConnAuthTokenSysMsgHdlr }
import org.bigbluebutton.core.apps.users.ChangeLockSettingsInMeetingCmdMsgHdlr
import org.bigbluebutton.core2.message.senders.MsgBuilder
import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender }
import org.bigbluebutton.core2.testdata.FakeTestData

object MeetingActor {
Expand Down Expand Up @@ -78,7 78,8 @@ class MeetingActor(
with ChangeLockSettingsInMeetingCmdMsgHdlr
with SyncGetMeetingInfoRespMsgHdlr
with ClientToServerLatencyTracerMsgHdlr
with ValidateConnAuthTokenSysMsgHdlr {
with ValidateConnAuthTokenSysMsgHdlr
with UserInactivityAuditResponseMsgHdlr {

override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
case e: Exception => {
Expand Down Expand Up @@ -165,11 166,11 @@ class MeetingActor(
// Set webcamsOnlyForModerator property in case we didn't after meeting creation
MeetingStatus2x.setWebcamsOnlyForModerator(liveMeeting.status, liveMeeting.props.usersProp.webcamsOnlyForModerator)

/*******************************************************************/
/** *****************************************************************/
// Helper to create fake users for testing (ralam jan 5, 2018)
//object FakeTestData extends FakeTestData
//FakeTestData.createFakeUsers(liveMeeting)
/*******************************************************************/
/** *****************************************************************/

def receive = {
//=============================
Expand Down Expand Up @@ -347,6 348,8 @@ class MeetingActor(

case m: ValidateConnAuthTokenSysMsg => handleValidateConnAuthTokenSysMsg(m)

case m: UserInactivityAuditResponseMsg => handleUserInactivityAuditResponseMsg(m)

case _ => log.warning("***** Cannot handle " msg.envelope.name)
}
}
Expand Down Expand Up @@ -409,6 412,8 @@ class MeetingActor(

sendRttTraceTest()
setRecordingChapterBreak()

processUserInactivityAudit()
}

var lastRecBreakSentOn = expiryTracker.startedOnInMs
Expand Down Expand Up @@ -502,7 507,46 @@ class MeetingActor(
"system", MeetingStatus2x.isRecording(liveMeeting.status)
)
outGW.send(event)
}
}

var lastUserInactivitySentOn = TimeUtil.timeNowInMs()
var checkInactiveUsers = false

def processUserInactivityAudit(): Unit = {
val now = TimeUtil.timeNowInMs()
if (now - lastUserInactivitySentOn > 30000) {
lastUserInactivitySentOn = now
checkInactiveUsers = true
val event = buildUserInactivityAuditMsg(liveMeeting.props.meetingProp.intId)
outGW.send(event)
}

if (checkInactiveUsers && now - lastUserInactivitySentOn > 10000) {
checkInactiveUsers = false
checkForInactiveUsers()
}
}

def checkForInactiveUsers(): Unit = {
val now = TimeUtil.timeNowInMs()
val users = Users2x.findAll(liveMeeting.users2x)
users foreach { u =>
if (now - u.inactivityResponseOn > 2000) {
UsersApp.ejectUserFromMeeting(outGW, liveMeeting, u.intId, SystemUser.ID, "User inactive for too long.", EjectReasonCode.USER_INACTIVITY)
Sender.sendDisconnectClientSysMsg(liveMeeting.props.meetingProp.intId, u.intId, SystemUser.ID, EjectReasonCode.USER_INACTIVITY, outGW)
}
}
}

def buildUserInactivityAuditMsg(meetingId: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "system")
val envelope = BbbCoreEnvelope(UserInactivityAuditMsg.NAME, routing)
val body = UserInactivityAuditMsgBody(meetingId)
val header = BbbClientMsgHeader(UserInactivityAuditMsg.NAME, meetingId, "system")
val event = UserInactivityAuditMsg(header, body)

BbbCommonEnvCoreMsg(envelope, event)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -358,3 358,12 @@ case class GetPresenterGroupReqMsgBody(requesterId: String)
object GetPresenterGroupRespMsg { val NAME = "GetPresenterGroupRespMsg" }
case class GetPresenterGroupRespMsg(header: BbbClientMsgHeader, body: GetPresenterGroupRespMsgBody) extends StandardMsg
case class GetPresenterGroupRespMsgBody(presenterGroup: Vector[String], requesterId: String)


object UserInactivityAuditMsg { val NAME = "UserInactivityAuditMsg" }
case class UserInactivityAuditMsg(header: BbbClientMsgHeader, body: UserInactivityAuditMsgBody) extends StandardMsg
case class UserInactivityAuditMsgBody(meetingId: String)

object UserInactivityAuditResponseMsg { val NAME = "UserInactivityAuditResponseMsg" }
case class UserInactivityAuditResponseMsg(header: BbbClientMsgHeader, body: UserInactivityAuditResponseMsgBody) extends StandardMsg
case class UserInactivityAuditResponseMsgBody(meetingId: String, userId: String)
1 change: 1 addition & 0 deletions bigbluebutton-client/locale/en_US/bbbResources.properties
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 551,7 @@ bbb.logout.breakoutRoomClose = Your browser window will be closed
bbb.logout.duplicateUserEjectReason = Duplicate user trying to join meeting.
bbb.logout.permissionEjectReason = Ejected due to permission violation.
bbb.logout.validateTokenFailedEjectReason = Failed to validate authorization token.
bbb.logout.userInactivityEjectReason = User inactive for too long.
bbb.logout.ejectedFromMeeting = You have been removed from the meeting.
bbb.logout.refresh.message = If this logout was unexpected click the button below to reconnect.
bbb.logout.refresh.label = Reconnect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 126,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
message = ResourceUtil.getInstance().getString('bbb.logout.ejectedFromMeeting');
} else if (reasonCode == "validate_token_failed_eject_reason") {
message = ResourceUtil.getInstance().getString('bbb.logout.validateTokenFailedEjectReason');
} else if (reasonCode == "user_inactivity_eject_reason") {
message = ResourceUtil.getInstance().getString('bbb.logout.userInactivityEjectReason');
}
break;
case ConnectionFailedEvent.USER_LOGGED_OUT:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 205,16 @@ package org.bigbluebutton.modules.users.services
case "GetGuestsWaitingApprovalRespMsg":
handleGetGuestsWaitingApprovalRespMsg(message);
break;
case "UserInactivityAuditMsg":
handleUserInactivityAuditMsg(message);
break;
}
}

private function handleUserInactivityAuditMsg(msg: Object):void {
trace("******************* RECEIVED USER INACTIVITY AUDIT!!!!! **********************");
}

private function handleUserJoinedVoiceConfToClientEvtMsg(msg: Object): void {
var header: Object = msg.header as Object;
var body: Object = msg.body as Object;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 20,10 @@ package org.bigbluebutton.air {
import org.bigbluebutton.air.main.commands.KickUserSignal;
import org.bigbluebutton.air.main.commands.LockUserCommand;
import org.bigbluebutton.air.main.commands.LockUserSignal;
import org.bigbluebutton.air.main.commands.UserInactivityTimerCommand;
import org.bigbluebutton.air.main.commands.UserInactivityTimerResponseCommand;
import org.bigbluebutton.air.main.commands.UserInactivityTimerResponseSignal;
import org.bigbluebutton.air.main.commands.UserInactivityTimerSignal;
import org.bigbluebutton.air.main.commands.PresenterCommand;
import org.bigbluebutton.air.main.commands.PresenterSignal;
import org.bigbluebutton.air.main.models.ConferenceParameters;
Expand Down Expand Up @@ -55,7 59,7 @@ package org.bigbluebutton.air {

import robotlegs.bender.extensions.signalCommandMap.api.ISignalCommandMap;
import robotlegs.bender.framework.api.IConfig;
import robotlegs.bender.framework.api.IInjector;
import robotlegs.bender.framework.api.IInjector;

public class AppConfig implements IConfig {

Expand Down Expand Up @@ -96,6 100,8 @@ package org.bigbluebutton.air {
signalCommandMap.map(LockUserSignal).toCommand(LockUserCommand);
signalCommandMap.map(ChangeUserRoleSignal).toCommand(ChangeUserRoleCommand);
signalCommandMap.map(KickUserSignal).toCommand(KickUserCommand);
signalCommandMap.map(UserInactivityTimerSignal).toCommand(UserInactivityTimerCommand);
signalCommandMap.map(UserInactivityTimerResponseSignal).toCommand(UserInactivityTimerResponseCommand);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ package org.bigbluebutton.air.common {
import org.bigbluebutton.air.chat.views.ChatRoomView;
import org.bigbluebutton.air.main.views.DisconnectView;
import org.bigbluebutton.air.main.views.ExitView;
import org.bigbluebutton.air.main.views.UserInactivityView;
import org.bigbluebutton.air.main.views.MainView;
import org.bigbluebutton.air.participants.views.ParticipantsView;
import org.bigbluebutton.air.settings.views.SettingsView;
Expand All @@ -14,7 15,7 @@ package org.bigbluebutton.air.common {
import org.bigbluebutton.air.settings.views.lock.LockSettingsView;
import org.bigbluebutton.air.user.views.UserDetailsView;
import org.bigbluebutton.air.voice.views.EchoTestView;
import org.bigbluebutton.air.voice.views.JoinAudioView;
import org.bigbluebutton.air.voice.views.JoinAudioView;

public class PageEnum {
public static const MAIN:String = "main";
Expand Down Expand Up @@ -49,6 50,8 @@ package org.bigbluebutton.air.common {

public static const APPLICATION_SETTINGS:String = "ApplicationSettings";

public static const INACTIVITY_VIEW:String = "InactivityView";

/**
* Especials
*/
Expand All @@ -74,6 77,7 @@ package org.bigbluebutton.air.common {
dic[DISCONNECT] = DisconnectView;
// dic[DESKSHARE] = DeskshareView;
dic[EXIT] = ExitView;
dic[INACTIVITY_VIEW] = UserInactivityView;
dicInitiated = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 1,21 @@
package org.bigbluebutton.air.main.commands
{
import org.bigbluebutton.air.main.models.IUISession;

import robotlegs.bender.bundles.mvcs.Command;

public class UserInactivityTimerCommand extends Command
{
[Inject]
public var uiSession:IUISession

public function UserInactivityTimerCommand()
{
super();
}

override public function execute():void {
trace("RECEIVED INACTIVITY TIMER MESSAGE");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 1,22 @@
package org.bigbluebutton.air.main.commands
{
import org.bigbluebutton.air.user.services.IUsersService;

import robotlegs.bender.bundles.mvcs.Command;

public class UserInactivityTimerResponseCommand extends Command
{

[Inject]
public var userService:IUsersService;

public function UserInactivityTimerResponseCommand()
{
super();
}

override public function execute():void {
userService.activityResponse();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 1,12 @@
package org.bigbluebutton.air.main.commands
{
import org.osflash.signals.Signal;

public class UserInactivityTimerResponseSignal extends Signal
{
public function UserInactivityTimerResponseSignal()
{
super();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 1,12 @@
package org.bigbluebutton.air.main.commands
{
import org.osflash.signals.Signal;

public class UserInactivityTimerSignal extends Signal
{
public function UserInactivityTimerSignal()
{
super();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 1,41 @@
package org.bigbluebutton.air.main.views
{
import spark.components.Button;
import spark.components.Label;
import spark.layouts.VerticalLayout;

import org.bigbluebutton.air.common.views.NoTabView;

public class UserInactivityView extends NoTabView
{
public var okButton:Button;

public function UserInactivityView()
{
super();

var l:VerticalLayout = new VerticalLayout();
l.horizontalAlign = "center";
layout = l;

var messageText:Label = new Label();
messageText.percentWidth = 90;
messageText.text = "Inacitivty Timer";
messageText.setStyle("textAlign", "center");
messageText.styleName = "disconnectMessage";
addElement(messageText);

okButton = new Button();
okButton.percentWidth = 90;
okButton.label = "Ok";
addElement(okButton);
}

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);

this.layout["gap"] = getStyle("gap");
this.layout["padding"] = getStyle("padding");
}
}
}
Loading

0 comments on commit 39284f1

Please sign in to comment.