- send destroy meeting to BBBActor when meeting ends

This commit is contained in:
Richard Alam 2017-07-17 09:13:07 -07:00
parent 6f2e3936b1
commit 1f50ec2da7
17 changed files with 178 additions and 186 deletions

View File

@ -59,10 +59,11 @@ class BigBlueButtonActor(
} }
def receive = { def receive = {
// Internal messages
case msg: DestroyMeetingInternalMsg => handleDestroyMeeting(msg)
// 2x messages // 2x messages
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg) case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
case msg: ValidateAuthToken => handleValidateAuthToken(msg)
case _ => // do nothing case _ => // do nothing
} }
@ -72,7 +73,6 @@ class BigBlueButtonActor(
case m: RegisterUserReqMsg => handleRegisterUserReqMsg(m) case m: RegisterUserReqMsg => handleRegisterUserReqMsg(m)
case m: GetAllMeetingsReqMsg => handleGetAllMeetingsReqMsg(m) case m: GetAllMeetingsReqMsg => handleGetAllMeetingsReqMsg(m)
case m: PubSubPingSysReqMsg => handlePubSubPingSysReqMsg(m) case m: PubSubPingSysReqMsg => handlePubSubPingSysReqMsg(m)
case m: DestroyMeetingSysCmdMsg => handleDestroyMeeting(m)
case _ => log.warning("Cannot handle " + msg.envelope.name) case _ => log.warning("Cannot handle " + msg.envelope.name)
} }
} }
@ -125,59 +125,17 @@ class BigBlueButtonActor(
}) })
} }
private def handleValidateAuthToken(msg: ValidateAuthToken) {
for {
m <- RunningMeetings.findWithId(meetings, msg.meetingID)
} yield {
m.actorRef forward (msg)
}
//meetings.get(msg.meetingID) foreach { m =>
// m.actorRef ! msg
// val future = m.actorRef.ask(msg)(5 seconds)
// future onComplete {
// case Success(result) => {
// log.info("Validate auth token response. meetingId=" + msg.meetingID + " userId=" + msg.userId + " token=" + msg.token)
// /**
// * Received a reply from MeetingActor which means hasn't hung!
// * Sometimes, the actor seems to hang and doesn't anymore accept messages. This is a simple
// * audit to check whether the actor is still alive. (ralam feb 25, 2015)
// */
// }
// case Failure(failure) => {
// log.warning("Validate auth token timeout. meetingId=" + msg.meetingID + " userId=" + msg.userId + " token=" + msg.token)
// outGW.send(new ValidateAuthTokenTimedOut(msg.meetingID, msg.userId, msg.token, false, msg.correlationId))
// }
// }
//}
}
private def handlePubSubPingSysReqMsg(msg: PubSubPingSysReqMsg): Unit = { private def handlePubSubPingSysReqMsg(msg: PubSubPingSysReqMsg): Unit = {
val event = MsgBuilder.buildPubSubPongSysRespMsg(msg.body.system, msg.body.timestamp) val event = MsgBuilder.buildPubSubPongSysRespMsg(msg.body.system, msg.body.timestamp)
outGW.send(event) outGW.send(event)
} }
private def handleDestroyMeeting(msg: DestroyMeetingSysCmdMsg): Unit = { private def handleDestroyMeeting(msg: DestroyMeetingInternalMsg): Unit = {
for { for {
m <- RunningMeetings.findWithId(meetings, msg.body.meetingId) m <- RunningMeetings.findWithId(meetings, msg.meetingId)
m2 <- RunningMeetings.remove(meetings, msg.body.meetingId) m2 <- RunningMeetings.remove(meetings, msg.meetingId)
} yield { } yield {
// send the message for MeetingActor to handle too
m.actorRef ! msg
// Delay sending DisconnectAllUsers because of RTMPT connection being dropped before UserEject message arrives to the client
context.system.scheduler.scheduleOnce(Duration.create(2500, TimeUnit.MILLISECONDS)) {
// Disconnect all clients
val disconnectEvnt = MsgBuilder.buildDisconnectAllClientsSysMsg(msg.body.meetingId)
outGW.send(disconnectEvnt)
log.info("Destroyed meetingId={}", msg.body.meetingId)
val destroyedEvent = MsgBuilder.buildMeetingDestroyedEvtMsg(msg.body.meetingId)
outGW.send(destroyedEvent)
/** Unsubscribe to meeting and voice events. **/ /** Unsubscribe to meeting and voice events. **/
eventBus.unsubscribe(m.actorRef, m.props.meetingProp.intId) eventBus.unsubscribe(m.actorRef, m.props.meetingProp.intId)
eventBus.unsubscribe(m.actorRef, m.props.voiceProp.voiceConf) eventBus.unsubscribe(m.actorRef, m.props.voiceProp.voiceConf)
@ -187,6 +145,18 @@ class BigBlueButtonActor(
bbbMsgBus.unsubscribe(m.actorRef, m.props.voiceProp.voiceConf) bbbMsgBus.unsubscribe(m.actorRef, m.props.voiceProp.voiceConf)
bbbMsgBus.unsubscribe(m.actorRef, m.props.screenshareProps.screenshareConf) bbbMsgBus.unsubscribe(m.actorRef, m.props.screenshareProps.screenshareConf)
// Delay sending DisconnectAllUsers to allow messages to reach the client
// before the connections are closed.
context.system.scheduler.scheduleOnce(Duration.create(2500, TimeUnit.MILLISECONDS)) {
// Disconnect all clients
val disconnectEvnt = MsgBuilder.buildDisconnectAllClientsSysMsg(msg.meetingId)
outGW.send(disconnectEvnt)
log.info("Destroyed meetingId={}", msg.meetingId)
val destroyedEvent = MsgBuilder.buildMeetingDestroyedEvtMsg(msg.meetingId)
outGW.send(destroyedEvent)
// Stop the meeting actor. // Stop the meeting actor.
context.stop(m.actorRef) context.stop(m.actorRef)
} }

View File

@ -78,7 +78,7 @@ class BigBlueButtonInGW(
eventBus.publish( eventBus.publish(
BigBlueButtonEvent( BigBlueButtonEvent(
"meeting-manager", "meeting-manager",
new DestroyMeeting( new DestroyMeetingInternalMsg(
meetingID meetingID
) )
) )

View File

@ -18,13 +18,18 @@ case class IsMeetingActorAliveMessage(meetingId: String) extends InMessage
case class KeepAliveMessage(aliveID: String) extends InMessage case class KeepAliveMessage(aliveID: String) extends InMessage
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Meeting // Internal Messages
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
case class MonitorNumberOfUsers(meetingID: String) extends InMessage case class MonitorNumberOfUsersInternalMsg(meetingID: String) extends InMessage
case class SendTimeRemainingUpdate(meetingId: String) extends InMessage case class SendTimeRemainingUpdate(meetingId: String) extends InMessage
case class ExtendMeetingDuration(meetingId: String, userId: String) extends InMessage case class ExtendMeetingDuration(meetingId: String, userId: String) extends InMessage
case class DestroyMeeting(meetingID: String) extends InMessage case class DestroyMeetingInternalMsg(meetingId: String) extends InMessage
case class BreakoutRoomEndedInternalMsg(meetingId: String) extends InMessage
//////////////////////////////////////////////////////////////////////////////
// Meeting
/////////////////////////////////////////////////////////////////////////////
case class StartMeeting(meetingID: String) extends InMessage case class StartMeeting(meetingID: String) extends InMessage
case class EndMeeting(meetingId: String) extends InMessage case class EndMeeting(meetingId: String) extends InMessage
case class LockSetting(meetingID: String, locked: Boolean, settings: Map[String, Boolean]) extends InMessage case class LockSetting(meetingID: String, locked: Boolean, settings: Map[String, Boolean]) extends InMessage

View File

@ -11,8 +11,6 @@ trait PresentationConversionCompletedPubMsgHdlr {
val outGW: OutMessageGateway val outGW: OutMessageGateway
def handlePresentationConversionCompletedPubMsg(msg: PresentationConversionCompletedSysPubMsg): Unit = { def handlePresentationConversionCompletedPubMsg(msg: PresentationConversionCompletedSysPubMsg): Unit = {
log.debug("**************** !!!!!PresentationConversionCompletedPubMsg ")
def broadcastEvent(msg: PresentationConversionCompletedSysPubMsg): Unit = { def broadcastEvent(msg: PresentationConversionCompletedSysPubMsg): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId) val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId)
val envelope = BbbCoreEnvelope(PresentationConversionCompletedEvtMsg.NAME, routing) val envelope = BbbCoreEnvelope(PresentationConversionCompletedEvtMsg.NAME, routing)

View File

@ -9,7 +9,7 @@ trait PresentationConversionUpdatePubMsgHdlr {
val outGW: OutMessageGateway val outGW: OutMessageGateway
def handlePresentationConversionUpdatePubMsg(msg: PresentationConversionUpdateSysPubMsg): Unit = { def handlePresentationConversionUpdatePubMsg(msg: PresentationConversionUpdateSysPubMsg): Unit = {
log.debug("**************** !!!!!PresentationConversionUpdateSysPubMsg " + msg.body.messageKey)
def broadcastEvent(msg: PresentationConversionUpdateSysPubMsg): Unit = { def broadcastEvent(msg: PresentationConversionUpdateSysPubMsg): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId) val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId)
val envelope = BbbCoreEnvelope(PresentationConversionUpdateEvtMsg.NAME, routing) val envelope = BbbCoreEnvelope(PresentationConversionUpdateEvtMsg.NAME, routing)

View File

@ -9,7 +9,6 @@ trait PresentationPageGeneratedPubMsgHdlr {
val outGW: OutMessageGateway val outGW: OutMessageGateway
def handlePresentationPageGeneratedPubMsg(msg: PresentationPageGeneratedSysPubMsg): Unit = { def handlePresentationPageGeneratedPubMsg(msg: PresentationPageGeneratedSysPubMsg): Unit = {
log.debug("**************** !!!!!PresentationPageGeneratedSysPubMsg " + msg.body.messageKey)
def broadcastEvent(msg: PresentationPageGeneratedSysPubMsg): Unit = { def broadcastEvent(msg: PresentationPageGeneratedSysPubMsg): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId) val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, liveMeeting.props.meetingProp.intId, msg.header.userId)

View File

@ -2,56 +2,34 @@ package org.bigbluebutton.core.apps.users
import org.bigbluebutton.common2.msgs._ import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.OutMessageGateway import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.api.{ EndMeeting, LogoutEndMeeting } import org.bigbluebutton.core.bus.{ IncomingEventBus }
import org.bigbluebutton.core.models.{ Roles, Users2x } import org.bigbluebutton.core.models.{ Roles, Users2x }
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting } import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core2.MeetingStatus2x
trait LogoutAndEndMeetingCmdMsgHdlr { trait LogoutAndEndMeetingCmdMsgHdlr {
this: UsersApp => this: UsersApp =>
val liveMeeting: LiveMeeting val liveMeeting: LiveMeeting
val outGW: OutMessageGateway val outGW: OutMessageGateway
val eventBus: IncomingEventBus
def handleLogoutAndEndMeetingCmdMsg(msg: LogoutAndEndMeetingCmdMsg) { def handleLogoutAndEndMeetingCmdMsg(msg: LogoutAndEndMeetingCmdMsg) {
for { for {
u <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId) u <- Users2x.findWithIntId(liveMeeting.users2x, msg.body.userId)
} yield { } yield {
if (u.role == Roles.MODERATOR_ROLE) { if (u.role == Roles.MODERATOR_ROLE) {
endMeeting() endMeeting(outGW, liveMeeting)
}
if (liveMeeting.props.meetingProp.isBreakout) {
log.info(
"Informing parent meeting {} that a breakout room has been ended {}",
liveMeeting.props.breakoutProps.parentId, liveMeeting.props.meetingProp.intId
)
notifyParentThatBreakoutEnded(eventBus, liveMeeting)
} }
def endMeeting(): Unit = { destroyMeeting(eventBus, liveMeeting.props.meetingProp.intId)
def buildMeetingEndingEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
val envelope = BbbCoreEnvelope(MeetingEndingEvtMsg.NAME, routing)
val body = MeetingEndingEvtMsgBody(meetingId)
val header = BbbClientMsgHeader(MeetingEndingEvtMsg.NAME, meetingId, "not-used")
val event = MeetingEndingEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
} }
val endingEvent = buildMeetingEndingEvtMsg(liveMeeting.props.meetingProp.intId)
// Broadcast users the meeting will end
outGW.send(endingEvent)
MeetingStatus2x.meetingHasEnded(liveMeeting.status)
def buildMeetingEndedEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(MeetingEndedEvtMsg.NAME, routing)
val body = MeetingEndedEvtMsgBody(meetingId)
val header = BbbCoreBaseHeader(MeetingEndedEvtMsg.NAME)
val event = MeetingEndedEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
val endedEvnt = buildMeetingEndedEvtMsg(liveMeeting.props.meetingProp.intId)
outGW.send(endedEvnt)
} }
} }
} }

View File

@ -13,9 +13,10 @@ trait MeetingActivityResponseCmdMsgHdlr {
def handleMeetingActivityResponseCmdMsg( def handleMeetingActivityResponseCmdMsg(
msg: MeetingActivityResponseCmdMsg, msg: MeetingActivityResponseCmdMsg,
tracker: MeetingInactivityTracker tracker: MeetingInactivityTracker,
helper: MeetingInactivityTrackerHelper
): MeetingInactivityTracker = { ): MeetingInactivityTracker = {
MeetingInactivityTrackerHelper.processMeetingActivityResponse( helper.processMeetingActivityResponse(
props = liveMeeting.props, props = liveMeeting.props,
outGW, outGW,
msg, msg,

View File

@ -3,12 +3,14 @@ package org.bigbluebutton.core.apps.users
import akka.actor.ActorContext import akka.actor.ActorContext
import akka.event.Logging import akka.event.Logging
import org.bigbluebutton.core.OutMessageGateway import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.bus.IncomingEventBus
import org.bigbluebutton.core.running.LiveMeeting import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core2.message.handlers.users.ValidateAuthTokenReqMsgHdlr import org.bigbluebutton.core2.message.handlers.users.ValidateAuthTokenReqMsgHdlr
class UsersApp( class UsersApp(
val liveMeeting: LiveMeeting, val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway val outGW: OutMessageGateway,
val eventBus: IncomingEventBus
)(implicit val context: ActorContext) )(implicit val context: ActorContext)
extends ValidateAuthTokenReqMsgHdlr extends ValidateAuthTokenReqMsgHdlr

View File

@ -1,13 +1,15 @@
package org.bigbluebutton.core.running package org.bigbluebutton.core.running
import org.bigbluebutton.SystemConfiguration
import org.bigbluebutton.common2.msgs._ import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.api.RecordingStatusChanged import org.bigbluebutton.core.api.{ BreakoutRoomEndedInternalMsg, DestroyMeetingInternalMsg, RecordingStatusChanged }
import org.bigbluebutton.core.bus.{ BigBlueButtonEvent, IncomingEventBus }
import org.bigbluebutton.core.{ MessageRecorder, OutMessageGateway } import org.bigbluebutton.core.{ MessageRecorder, OutMessageGateway }
import org.bigbluebutton.core.models._ import org.bigbluebutton.core.models._
import org.bigbluebutton.core2.MeetingStatus2x import org.bigbluebutton.core2.MeetingStatus2x
import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender, UserJoinedMeetingEvtMsgBuilder } import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender, UserJoinedMeetingEvtMsgBuilder }
trait HandlerHelpers { trait HandlerHelpers extends SystemConfiguration {
def validateTokenFailed(outGW: OutMessageGateway, meetingId: String, userId: String, authToken: String, def validateTokenFailed(outGW: OutMessageGateway, meetingId: String, userId: String, authToken: String,
valid: Boolean, waitForApproval: Boolean): Unit = { valid: Boolean, waitForApproval: Boolean): Unit = {
@ -136,7 +138,6 @@ trait HandlerHelpers {
val event = UserJoinedMeetingEvtMsgBuilder.build(liveMeeting.props.meetingProp.intId, userState) val event = UserJoinedMeetingEvtMsgBuilder.build(liveMeeting.props.meetingProp.intId, userState)
Sender.send(outGW, event) Sender.send(outGW, event)
MessageRecorder.record(outGW, liveMeeting.props.recordProp.record, event.core)
startRecordingIfAutoStart2x(liveMeeting) startRecordingIfAutoStart2x(liveMeeting)
} }
} }
@ -165,4 +166,47 @@ trait HandlerHelpers {
def event = MsgBuilder.buildPresenterAssignedEvtMsg(meetingId, intId, name, assignedBy) def event = MsgBuilder.buildPresenterAssignedEvtMsg(meetingId, intId, name, assignedBy)
outGW.send(event) outGW.send(event)
} }
def endMeeting(outGW: OutMessageGateway, liveMeeting: LiveMeeting): Unit = {
def buildMeetingEndingEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
val envelope = BbbCoreEnvelope(MeetingEndingEvtMsg.NAME, routing)
val body = MeetingEndingEvtMsgBody(meetingId)
val header = BbbClientMsgHeader(MeetingEndingEvtMsg.NAME, meetingId, "not-used")
val event = MeetingEndingEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
val endingEvent = buildMeetingEndingEvtMsg(liveMeeting.props.meetingProp.intId)
// Broadcast users the meeting will end
outGW.send(endingEvent)
MeetingStatus2x.meetingHasEnded(liveMeeting.status)
def buildMeetingEndedEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(MeetingEndedEvtMsg.NAME, routing)
val body = MeetingEndedEvtMsgBody(meetingId)
val header = BbbCoreBaseHeader(MeetingEndedEvtMsg.NAME)
val event = MeetingEndedEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
val endedEvnt = buildMeetingEndedEvtMsg(liveMeeting.props.meetingProp.intId)
outGW.send(endedEvnt)
}
def destroyMeeting(eventBus: IncomingEventBus, meetingId: String): Unit = {
eventBus.publish(BigBlueButtonEvent(meetingManagerChannel, new DestroyMeetingInternalMsg(meetingId)))
}
def notifyParentThatBreakoutEnded(eventBus: IncomingEventBus, liveMeeting: LiveMeeting): Unit = {
eventBus.publish(BigBlueButtonEvent(
liveMeeting.props.breakoutProps.parentId,
new BreakoutRoomEndedInternalMsg(liveMeeting.props.meetingProp.intId)
))
}
} }

View File

@ -102,7 +102,7 @@ class MeetingActor(
val captionApp2x = new CaptionApp2x(liveMeeting, outGW) val captionApp2x = new CaptionApp2x(liveMeeting, outGW)
val sharedNotesApp2x = new SharedNotesApp2x(liveMeeting, outGW) val sharedNotesApp2x = new SharedNotesApp2x(liveMeeting, outGW)
val chatApp2x = new ChatApp2x(liveMeeting, outGW) val chatApp2x = new ChatApp2x(liveMeeting, outGW)
val usersApp = new UsersApp(liveMeeting, outGW) val usersApp = new UsersApp(liveMeeting, outGW, eventBus)
var inactivityTracker = new MeetingInactivityTracker( var inactivityTracker = new MeetingInactivityTracker(
liveMeeting.props.durationProps.maxInactivityTimeoutMinutes, liveMeeting.props.durationProps.maxInactivityTimeoutMinutes,
@ -110,11 +110,15 @@ class MeetingActor(
TimeUtil.millisToMinutes(System.currentTimeMillis()), false, 0L TimeUtil.millisToMinutes(System.currentTimeMillis()), false, 0L
) )
val inactivityTrackerHelper = new MeetingInactivityTrackerHelper(liveMeeting, outGW)
var expiryTracker = new MeetingExpiryTracker( var expiryTracker = new MeetingExpiryTracker(
TimeUtil.millisToMinutes(System.currentTimeMillis()), TimeUtil.millisToMinutes(System.currentTimeMillis()),
false, 0L false, 0L
) )
val expiryTrackerHelper = new MeetingExpiryTrackerHelper(liveMeeting, outGW)
/*******************************************************************/ /*******************************************************************/
//object FakeTestData extends FakeTestData //object FakeTestData extends FakeTestData
//FakeTestData.createFakeUsers(liveMeeting) //FakeTestData.createFakeUsers(liveMeeting)
@ -137,7 +141,7 @@ class MeetingActor(
//======================================= //=======================================
// old messages // old messages
case msg: MonitorNumberOfUsers => handleMonitorNumberOfUsers(msg) case msg: MonitorNumberOfUsersInternalMsg => handleMonitorNumberOfUsers(msg)
case msg: AllowUserToShareDesktop => handleAllowUserToShareDesktop(msg) case msg: AllowUserToShareDesktop => handleAllowUserToShareDesktop(msg)
case msg: ExtendMeetingDuration => handleExtendMeetingDuration(msg) case msg: ExtendMeetingDuration => handleExtendMeetingDuration(msg)
@ -165,7 +169,8 @@ class MeetingActor(
case m: UserBroadcastCamStartMsg => handleUserBroadcastCamStartMsg(m) case m: UserBroadcastCamStartMsg => handleUserBroadcastCamStartMsg(m)
case m: UserBroadcastCamStopMsg => handleUserBroadcastCamStopMsg(m) case m: UserBroadcastCamStopMsg => handleUserBroadcastCamStopMsg(m)
case m: UserJoinedVoiceConfEvtMsg => handleUserJoinedVoiceConfEvtMsg(m) case m: UserJoinedVoiceConfEvtMsg => handleUserJoinedVoiceConfEvtMsg(m)
case m: MeetingActivityResponseCmdMsg => inactivityTracker = usersApp.handleMeetingActivityResponseCmdMsg(m, inactivityTracker) case m: MeetingActivityResponseCmdMsg =>
inactivityTracker = usersApp.handleMeetingActivityResponseCmdMsg(m, inactivityTracker, inactivityTrackerHelper)
case m: LogoutAndEndMeetingCmdMsg => usersApp.handleLogoutAndEndMeetingCmdMsg(m) case m: LogoutAndEndMeetingCmdMsg => usersApp.handleLogoutAndEndMeetingCmdMsg(m)
case m: SetRecordingStatusCmdMsg => usersApp.handleSetRecordingStatusCmdMsg(m) case m: SetRecordingStatusCmdMsg => usersApp.handleSetRecordingStatusCmdMsg(m)
case m: GetRecordingStatusReqMsg => usersApp.handleGetRecordingStatusReqMsg(m) case m: GetRecordingStatusReqMsg => usersApp.handleGetRecordingStatusReqMsg(m)
@ -329,15 +334,15 @@ class MeetingActor(
} }
} }
def handleMonitorNumberOfUsers(msg: MonitorNumberOfUsers) { def handleMonitorNumberOfUsers(msg: MonitorNumberOfUsersInternalMsg) {
inactivityTracker = MeetingInactivityTrackerHelper.processMeetingInactivityAudit( inactivityTracker = inactivityTrackerHelper.processMeetingInactivityAudit(
props = liveMeeting.props, props = liveMeeting.props,
outGW, outGW,
eventBus, eventBus,
inactivityTracker inactivityTracker
) )
expiryTracker = MeetingExpiryTracker.processMeetingExpiryAudit(liveMeeting.props, expiryTracker, eventBus) expiryTracker = expiryTrackerHelper.processMeetingExpiryAudit(liveMeeting.props, expiryTracker, eventBus)
monitorNumberOfWebUsers() monitorNumberOfWebUsers()
monitorNumberOfUsers() monitorNumberOfUsers()

View File

@ -72,7 +72,7 @@ class MeetingActorAudit(
} }
def handleMonitorNumberOfWebUsers() { def handleMonitorNumberOfWebUsers() {
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, MonitorNumberOfUsers(props.meetingProp.intId))) eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, MonitorNumberOfUsersInternalMsg(props.meetingProp.intId)))
// Trigger updating users of time remaining on meeting. // Trigger updating users of time remaining on meeting.
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, SendTimeRemainingUpdate(props.meetingProp.intId))) eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, SendTimeRemainingUpdate(props.meetingProp.intId)))

View File

@ -1,12 +1,19 @@
package org.bigbluebutton.core.running package org.bigbluebutton.core.running
import akka.actor.ActorContext
import akka.event.Logging
import org.bigbluebutton.common2.domain.DefaultProps import org.bigbluebutton.common2.domain.DefaultProps
import org.bigbluebutton.core.api.EndMeeting import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.bus.{ BigBlueButtonEvent, IncomingEventBus } import org.bigbluebutton.core.bus.{ IncomingEventBus }
import org.bigbluebutton.core.domain.MeetingExpiryTracker import org.bigbluebutton.core.domain.MeetingExpiryTracker
import org.bigbluebutton.core.util.TimeUtil import org.bigbluebutton.core.util.TimeUtil
object MeetingExpiryTracker { class MeetingExpiryTrackerHelper(
val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway
)(implicit val context: ActorContext) extends HandlerHelpers {
val log = Logging(context.system, getClass)
def hasMeetingExpiredNeverBeenJoined(nowInMinutes: Long, startedOnInMinutes: Long, meetingExpireIfNoUserJoinedInMinutes: Long): Boolean = { def hasMeetingExpiredNeverBeenJoined(nowInMinutes: Long, startedOnInMinutes: Long, meetingExpireIfNoUserJoinedInMinutes: Long): Boolean = {
nowInMinutes - startedOnInMinutes > meetingExpireIfNoUserJoinedInMinutes nowInMinutes - startedOnInMinutes > meetingExpireIfNoUserJoinedInMinutes
@ -19,6 +26,7 @@ object MeetingExpiryTracker {
def processNeverBeenJoinedExpiry(nowInMinutes: Long, props: DefaultProps, tracker: MeetingExpiryTracker, eventBus: IncomingEventBus): MeetingExpiryTracker = { def processNeverBeenJoinedExpiry(nowInMinutes: Long, props: DefaultProps, tracker: MeetingExpiryTracker, eventBus: IncomingEventBus): MeetingExpiryTracker = {
if (hasMeetingExpiredNeverBeenJoined(nowInMinutes, tracker.startedOnInMinutes, if (hasMeetingExpiredNeverBeenJoined(nowInMinutes, tracker.startedOnInMinutes,
props.durationProps.meetingExpireIfNoUserJoinedInMinutes)) { props.durationProps.meetingExpireIfNoUserJoinedInMinutes)) {
log.info("Ending meeting as it has never been joined.")
sendEndMeetingDueToExpiry(props, eventBus) sendEndMeetingDueToExpiry(props, eventBus)
tracker tracker
} else { } else {
@ -32,7 +40,8 @@ object MeetingExpiryTracker {
if (!tracker.meetingJoined) { if (!tracker.meetingJoined) {
processNeverBeenJoinedExpiry(nowInMinutes, props, tracker, eventBus) processNeverBeenJoinedExpiry(nowInMinutes, props, tracker, eventBus)
} else { } else {
if (meetingOverDuration(nowInMinutes, tracker.startedOnInMinutes, props.durationProps.duration)) { if (props.durationProps.duration != 0 && meetingOverDuration(nowInMinutes, tracker.startedOnInMinutes, props.durationProps.duration)) {
log.info("Ending meeting as it has passed duration.")
sendEndMeetingDueToExpiry(props, eventBus) sendEndMeetingDueToExpiry(props, eventBus)
tracker tracker
} else { } else {
@ -42,6 +51,17 @@ object MeetingExpiryTracker {
} }
def sendEndMeetingDueToExpiry(props: DefaultProps, eventBus: IncomingEventBus): Unit = { def sendEndMeetingDueToExpiry(props: DefaultProps, eventBus: IncomingEventBus): Unit = {
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, EndMeeting(props.meetingProp.intId)))
endMeeting(outGW, liveMeeting)
if (liveMeeting.props.meetingProp.isBreakout) {
log.info(
"Informing parent meeting {} that a breakout room has been ended {}",
liveMeeting.props.breakoutProps.parentId, liveMeeting.props.meetingProp.intId
)
notifyParentThatBreakoutEnded(eventBus, liveMeeting)
}
destroyMeeting(eventBus, liveMeeting.props.meetingProp.intId)
} }
} }

View File

@ -1,15 +1,21 @@
package org.bigbluebutton.core.running package org.bigbluebutton.core.running
import akka.actor.ActorContext
import akka.event.Logging
import org.bigbluebutton.core.domain.MeetingInactivityTracker import org.bigbluebutton.core.domain.MeetingInactivityTracker
import com.softwaremill.quicklens._ import com.softwaremill.quicklens._
import org.bigbluebutton.common2.domain.DefaultProps import org.bigbluebutton.common2.domain.DefaultProps
import org.bigbluebutton.common2.msgs._ import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.OutMessageGateway import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.api.EndMeeting import org.bigbluebutton.core.bus.{ IncomingEventBus }
import org.bigbluebutton.core.bus.{ BigBlueButtonEvent, IncomingEventBus }
import org.bigbluebutton.core.util.TimeUtil import org.bigbluebutton.core.util.TimeUtil
object MeetingInactivityTrackerHelper { class MeetingInactivityTrackerHelper(
val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway
)(implicit val context: ActorContext) extends HandlerHelpers {
val log = Logging(context.system, getClass)
def isMeetingActive( def isMeetingActive(
nowInMinutes: Long, nowInMinutes: Long,
@ -67,7 +73,17 @@ object MeetingInactivityTrackerHelper {
} }
def sendEndMeetingDueToInactivity(props: DefaultProps, eventBus: IncomingEventBus): Unit = { def sendEndMeetingDueToInactivity(props: DefaultProps, eventBus: IncomingEventBus): Unit = {
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, EndMeeting(props.meetingProp.intId))) endMeeting(outGW, liveMeeting)
if (liveMeeting.props.meetingProp.isBreakout) {
log.info(
"Informing parent meeting {} that a breakout room has been ended {}",
liveMeeting.props.breakoutProps.parentId, liveMeeting.props.meetingProp.intId
)
notifyParentThatBreakoutEnded(eventBus, liveMeeting)
}
destroyMeeting(eventBus, liveMeeting.props.meetingProp.intId)
} }
def sendMeetingInactivityWarning(props: DefaultProps, outGW: OutMessageGateway, timeLeftSeconds: Long): Unit = { def sendMeetingInactivityWarning(props: DefaultProps, outGW: OutMessageGateway, timeLeftSeconds: Long): Unit = {

View File

@ -3,7 +3,6 @@ package org.bigbluebutton.core2.message.handlers.meeting
import org.bigbluebutton.common2.msgs._ import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.OutMessageGateway import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting } import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting }
import org.bigbluebutton.core2.MeetingStatus2x
import org.bigbluebutton.core2.message.senders.MsgBuilder import org.bigbluebutton.core2.message.senders.MsgBuilder
trait DestroyMeetingSysCmdMsgHdlr { trait DestroyMeetingSysCmdMsgHdlr {

View File

@ -2,24 +2,28 @@ package org.bigbluebutton.core2.message.handlers.meeting
import org.bigbluebutton.common2.msgs._ import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.OutMessageGateway import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting } import org.bigbluebutton.core.bus.IncomingEventBus
import org.bigbluebutton.core2.MeetingStatus2x import org.bigbluebutton.core.running.{ BaseMeetingActor, HandlerHelpers, LiveMeeting }
import org.bigbluebutton.core2.message.senders.MsgBuilder
trait EndMeetingSysCmdMsgHdlr { trait EndMeetingSysCmdMsgHdlr extends HandlerHelpers {
this: BaseMeetingActor => this: BaseMeetingActor =>
val liveMeeting: LiveMeeting val liveMeeting: LiveMeeting
val outGW: OutMessageGateway val outGW: OutMessageGateway
val eventBus: IncomingEventBus
def handleEndMeeting(msg: EndMeetingSysCmdMsg) { def handleEndMeeting(msg: EndMeetingSysCmdMsg) {
// Broadcast users the meeting will end endMeeting(outGW, liveMeeting)
outGW.send(MsgBuilder.buildMeetingEndingEvtMsg(liveMeeting.props.meetingProp.intId))
MeetingStatus2x.meetingHasEnded(liveMeeting.status) if (liveMeeting.props.meetingProp.isBreakout) {
log.info(
"Informing parent meeting {} that a breakout room has been ended {}",
liveMeeting.props.breakoutProps.parentId, liveMeeting.props.meetingProp.intId
)
notifyParentThatBreakoutEnded(eventBus, liveMeeting)
}
// Sent from akka-apps to bbb-web to inform about end of meeting destroyMeeting(eventBus, liveMeeting.props.meetingProp.intId)
outGW.send(MsgBuilder.buildMeetingEndedEvtMsg(liveMeeting.props.meetingProp.intId))
} }
} }

View File

@ -1,49 +0,0 @@
package org.bigbluebutton.core2.message.handlers.users
import org.bigbluebutton.common2.domain.VoiceUserVO
import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.api._
import org.bigbluebutton.core.models._
import org.bigbluebutton.core.running.MeetingActor
import org.bigbluebutton.core2.MeetingStatus2x
trait UserJoiningHdlr {
this: MeetingActor =>
val outGW: OutMessageGateway
def handleUserJoin(msg: UserJoining): Unit = {
log.debug("Received user joined meeting. metingId=" + props.meetingProp.intId + " userId=" + msg.userID)
/*
for {
uvo <- Users.newUser(msg.userID, lockStatus, ru, waitingForAcceptance, vu, liveMeeting.users)
} yield {
log.info("User joined meeting. metingId=" + props.meetingProp.intId + " userId=" + uvo.id + " user=" + uvo)
if (uvo.guest && MeetingStatus2x.getGuestPolicy(liveMeeting.status) == GuestPolicy.ALWAYS_DENY) {
outGW.send(new GuestAccessDenied(props.meetingProp.intId, props.recordProp.record, uvo.id))
} else {
outGW.send(new UserJoined(props.meetingProp.intId, props.recordProp.record, uvo))
outGW.send(new MeetingState(props.meetingProp.intId, props.recordProp.record, uvo.id,
MeetingStatus2x.getPermissions(liveMeeting.status), MeetingStatus2x.isMeetingMuted(liveMeeting.status)))
if (!waitingForAcceptance) {
// Become presenter if the only moderator
if ((Users.numModerators(liveMeeting.users) == 1) || (Users.hasNoPresenter(liveMeeting.users))) {
if (ru.role == Roles.MODERATOR_ROLE) {
log.info("Assigning presenter to lone moderator. metingId=" + props.meetingProp.intId + " userId=" + uvo.id)
assignNewPresenter(msg.userID, ru.name, msg.userID)
}
}
} else {
log.info("User waiting for acceptance. metingId=" + props.meetingProp.intId + " userId=" + uvo.id)
}
liveMeeting.webUserJoined
startRecordingIfAutoStart()
}
}
*/
}
}