- try writing test

- start implementing meeting inactivity
 - updated scalariform to format scala code
This commit is contained in:
Richard Alam 2017-07-14 14:50:34 -07:00
parent 08fe6cea81
commit 80213da06e
88 changed files with 999 additions and 745 deletions

View File

@ -25,6 +25,7 @@ resolvers ++= Seq(
)
resolvers += Resolver.sonatypeRepo("releases")
resolvers += Resolver.typesafeRepo("releases")
publishTo := Some(Resolver.file("file", new File(Path.userHome.absolutePath+"/dev/repo/maven-repo/releases" )) )
@ -90,9 +91,21 @@ libraryDependencies += "org.scalatest" % "scalatest_2.12" % "3.0.3" % "test"
libraryDependencies += "org.mockito" % "mockito-core" % "2.7.22" % "test"
seq(Revolver.settings: _*)
scalariformSettings
import com.typesafe.sbt.SbtScalariform
import scalariform.formatter.preferences._
import com.typesafe.sbt.SbtScalariform.ScalariformKeys
SbtScalariform.defaultScalariformSettings
ScalariformKeys.preferences := ScalariformKeys.preferences.value
.setPreference(AlignSingleLineCaseStatements, true)
.setPreference(DoubleIndentClassDeclaration, true)
.setPreference(AlignParameters, true)
//-----------

View File

@ -1,6 +1,8 @@
addSbtPlugin("io.spray" % "sbt-revolver" % "0.7.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.3.0")
//addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.3.0")
addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.6.0")
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.2.0")

View File

@ -15,7 +15,8 @@ object Boot extends App with SystemConfiguration {
implicit val executor = system.dispatcher
val logger = Logging(system, getClass)
val eventBus = new IncomingEventBus
val eventBus = new InMsgBusGW(new IncomingEventBusImp())
val outgoingEventBus = new OutgoingEventBus
val outBus2 = new OutEventBus2
val recordingEventBus = new RecordingEventBus

View File

@ -19,16 +19,20 @@ import org.bigbluebutton.core2.RunningMeetings
import org.bigbluebutton.core2.message.senders.MsgBuilder
object BigBlueButtonActor extends SystemConfiguration {
def props(system: ActorSystem,
eventBus: IncomingEventBus,
def props(
system: ActorSystem,
eventBus: IncomingEventBus,
bbbMsgBus: BbbMsgRouterEventBus,
outGW: OutMessageGateway): Props =
outGW: OutMessageGateway
): Props =
Props(classOf[BigBlueButtonActor], system, eventBus, bbbMsgBus, outGW)
}
class BigBlueButtonActor(val system: ActorSystem,
class BigBlueButtonActor(
val system: ActorSystem,
val eventBus: IncomingEventBus, val bbbMsgBus: BbbMsgRouterEventBus,
val outGW: OutMessageGateway) extends Actor
val outGW: OutMessageGateway
) extends Actor
with ActorLogging with SystemConfiguration {
implicit def executionContext = system.dispatcher
@ -56,27 +60,27 @@ class BigBlueButtonActor(val system: ActorSystem,
def receive = {
// 2x messages
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
// 1x messages
case msg: ValidateAuthToken => handleValidateAuthToken(msg)
case msg: UserJoinedVoiceConfMessage => handleUserJoinedVoiceConfMessage(msg)
case msg: UserLeftVoiceConfMessage => handleUserLeftVoiceConfMessage(msg)
case msg: UserLockedInVoiceConfMessage => handleUserLockedInVoiceConfMessage(msg)
case msg: UserMutedInVoiceConfMessage => handleUserMutedInVoiceConfMessage(msg)
case msg: UserTalkingInVoiceConfMessage => handleUserTalkingInVoiceConfMessage(msg)
case msg: ValidateAuthToken => handleValidateAuthToken(msg)
case msg: UserJoinedVoiceConfMessage => handleUserJoinedVoiceConfMessage(msg)
case msg: UserLeftVoiceConfMessage => handleUserLeftVoiceConfMessage(msg)
case msg: UserLockedInVoiceConfMessage => handleUserLockedInVoiceConfMessage(msg)
case msg: UserMutedInVoiceConfMessage => handleUserMutedInVoiceConfMessage(msg)
case msg: UserTalkingInVoiceConfMessage => handleUserTalkingInVoiceConfMessage(msg)
case msg: VoiceConfRecordingStartedMessage => handleVoiceConfRecordingStartedMessage(msg)
case _ => // do nothing
case _ => // do nothing
}
private def handleBbbCommonEnvCoreMsg(msg: BbbCommonEnvCoreMsg): Unit = {
msg.core match {
case m: CreateMeetingReqMsg => handleCreateMeetingReqMsg(m)
case m: RegisterUserReqMsg => handleRegisterUserReqMsg(m)
case m: GetAllMeetingsReqMsg => handleGetAllMeetingsReqMsg(m)
case m: PubSubPingSysReqMsg => handlePubSubPingSysReqMsg(m)
case m: CreateMeetingReqMsg => handleCreateMeetingReqMsg(m)
case m: RegisterUserReqMsg => handleRegisterUserReqMsg(m)
case m: GetAllMeetingsReqMsg => handleGetAllMeetingsReqMsg(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)
}
}
@ -94,7 +98,7 @@ class BigBlueButtonActor(val system: ActorSystem,
log.debug("****** RECEIVED CreateMeetingReqMsg msg {}", msg)
RunningMeetings.findWithId(meetings, msg.body.props.meetingProp.intId) match {
case None => {
case None =>
log.info("Create meeting request. meetingId={}", msg.body.props.meetingProp.intId)
val m = RunningMeeting(msg.body.props, outGW, eventBus)
@ -115,11 +119,11 @@ class BigBlueButtonActor(val system: ActorSystem,
// Send new 2x message
val msgEvent = MsgBuilder.buildMeetingCreatedEvtMsg(m.props.meetingProp.intId, msg.body.props)
outGW.send(msgEvent)
}
case Some(m) => {
case Some(m) =>
log.info("Meeting already created. meetingID={}", msg.body.props.meetingProp.intId)
// do nothing
}
// do nothing
}
}

View File

@ -19,9 +19,10 @@ import scala.collection.JavaConverters
class BigBlueButtonInGW(
val system: ActorSystem,
eventBus: IncomingEventBus,
bbbMsgBus: BbbMsgRouterEventBus,
outGW: OutMessageGateway) extends IBigBlueButtonInGW with SystemConfiguration {
eventBus: IncomingEventBus,
bbbMsgBus: BbbMsgRouterEventBus,
outGW: OutMessageGateway
) extends IBigBlueButtonInGW with SystemConfiguration {
val log = Logging(system, getClass)
val bbbActor = system.actorOf(BigBlueButtonActor.props(system, eventBus, bbbMsgBus, outGW), "bigbluebutton-actor")
@ -34,22 +35,26 @@ class BigBlueButtonInGW(
message match {
case msg: StartCustomPollRequestMessage => {
eventBus.publish(
BigBlueButtonEvent(msg.payload.meetingId,
BigBlueButtonEvent(
msg.payload.meetingId,
new StartCustomPollRequest(msg.payload.meetingId, msg.payload.requesterId,
msg.payload.pollId, msg.payload.pollType, msg.payload.answers)))
msg.payload.pollId, msg.payload.pollType, msg.payload.answers)
)
)
}
case msg: PubSubPingMessage => {
eventBus.publish(
BigBlueButtonEvent("meeting-manager", new PubSubPing(msg.payload.system, msg.payload.timestamp)))
BigBlueButtonEvent("meeting-manager", new PubSubPing(msg.payload.system, msg.payload.timestamp))
)
}
case msg: CreateMeetingRequest => {
val policy = msg.payload.guestPolicy.toUpperCase() match {
case "ALWAYS_ACCEPT" => GuestPolicyType.ALWAYS_ACCEPT
case "ALWAYS_DENY" => GuestPolicyType.ALWAYS_DENY
case "ALWAYS_DENY" => GuestPolicyType.ALWAYS_DENY
case "ASK_MODERATOR" => GuestPolicyType.ASK_MODERATOR
//default
case undef => GuestPolicyType.ASK_MODERATOR
case undef => GuestPolicyType.ASK_MODERATOR
}
/*
val mProps = new MeetingProperties(
@ -84,18 +89,18 @@ class BigBlueButtonInGW(
def handleJsonMessage(json: String) {
JsonMessageDecoder.decode(json) match {
case Some(validMsg) => forwardMessage(validMsg)
case None => log.error("Unhandled json message: {}", json)
case None => log.error("Unhandled json message: {}", json)
}
}
def forwardMessage(msg: InMessage) = {
msg match {
case m: BreakoutRoomsListMessage => eventBus.publish(BigBlueButtonEvent(m.meetingId, m))
case m: CreateBreakoutRooms => eventBus.publish(BigBlueButtonEvent(m.meetingId, m))
case m: BreakoutRoomsListMessage => eventBus.publish(BigBlueButtonEvent(m.meetingId, m))
case m: CreateBreakoutRooms => eventBus.publish(BigBlueButtonEvent(m.meetingId, m))
case m: RequestBreakoutJoinURLInMessage => eventBus.publish(BigBlueButtonEvent(m.meetingId, m))
case m: TransferUserToMeetingRequest => eventBus.publish(BigBlueButtonEvent(m.meetingId, m))
case m: EndAllBreakoutRooms => eventBus.publish(BigBlueButtonEvent(m.meetingId, m))
case _ => log.error("Unhandled message: {}", msg)
case m: TransferUserToMeetingRequest => eventBus.publish(BigBlueButtonEvent(m.meetingId, m))
case m: EndAllBreakoutRooms => eventBus.publish(BigBlueButtonEvent(m.meetingId, m))
case _ => log.error("Unhandled message: {}", msg)
}
}
@ -105,7 +110,10 @@ class BigBlueButtonInGW(
BigBlueButtonEvent(
"meeting-manager",
new DestroyMeeting(
meetingID)))
meetingID
)
)
)
}
def getAllMeetings(meetingID: String) {
@ -117,7 +125,7 @@ class BigBlueButtonInGW(
}
def lockSettings(meetingID: String, locked: java.lang.Boolean,
lockSettings: java.util.Map[String, java.lang.Boolean]) {
lockSettings: java.util.Map[String, java.lang.Boolean]) {
}
def statusMeetingAudit(meetingID: String) {
@ -146,7 +154,7 @@ class BigBlueButtonInGW(
}
def registerUser(meetingID: String, userID: String, name: String, role: String, extUserID: String,
authToken: String, avatarURL: String, guest: java.lang.Boolean, authed: java.lang.Boolean): Unit = {
authToken: String, avatarURL: String, guest: java.lang.Boolean, authed: java.lang.Boolean): Unit = {
val userRole = if (role == "MODERATOR") Roles.MODERATOR_ROLE else Roles.VIEWER_ROLE
eventBus.publish(BigBlueButtonEvent(meetingID, new RegisterUser(meetingID, userID, name, userRole,
extUserID, authToken, avatarURL, guest, authed)))
@ -166,13 +174,15 @@ class BigBlueButtonInGW(
val lockOnJoin = s.getOrElse("lockOnJoin", false)
val lockOnJoinConfigurable = s.getOrElse("lockOnJoinConfigurable", false)
val permissions = new Permissions(disableCam = disableCam,
val permissions = new Permissions(
disableCam = disableCam,
disableMic = disableMic,
disablePrivChat = disablePrivChat,
disablePubChat = disablePubChat,
lockedLayout = lockedLayout,
lockOnJoin = lockOnJoin,
lockOnJoinConfigurable = lockOnJoinConfigurable)
lockOnJoinConfigurable = lockOnJoinConfigurable
)
eventBus.publish(BigBlueButtonEvent(meetingID, new SetLockSettings(meetingID, userId, permissions)))
}
@ -190,13 +200,15 @@ class BigBlueButtonInGW(
val lockedLayout = s.getOrElse("lockedLayout", false)
val lockOnJoin = s.getOrElse("lockOnJoin", false)
val lockOnJoinConfigurable = s.getOrElse("lockOnJoinConfigurable", false)
val permissions = new Permissions(disableCam = disableCam,
val permissions = new Permissions(
disableCam = disableCam,
disableMic = disableMic,
disablePrivChat = disablePrivChat,
disablePubChat = disablePubChat,
lockedLayout = lockedLayout,
lockOnJoin = lockOnJoin,
lockOnJoinConfigurable = lockOnJoinConfigurable)
lockOnJoinConfigurable = lockOnJoinConfigurable
)
eventBus.publish(BigBlueButtonEvent(meetingID, new InitLockSettings(meetingID, permissions)))
}
@ -263,8 +275,10 @@ class BigBlueButtonInGW(
}
def checkIfAllowedToShareDesktop(meetingID: String, userID: String): Unit = {
eventBus.publish(BigBlueButtonEvent(meetingID, AllowUserToShareDesktop(meetingID: String,
userID: String)))
eventBus.publish(BigBlueButtonEvent(meetingID, AllowUserToShareDesktop(
meetingID: String,
userID: String
)))
}
def assignPresenter(meetingID: String, newPresenterID: String, newPresenterName: String, assignedBy: String): Unit = {
@ -300,10 +314,10 @@ class BigBlueButtonInGW(
def setGuestPolicy(meetingId: String, guestPolicy: String, requesterId: String) {
val policy = guestPolicy.toUpperCase() match {
case "ALWAYS_ACCEPT" => GuestPolicyType.ALWAYS_ACCEPT
case "ALWAYS_DENY" => GuestPolicyType.ALWAYS_DENY
case "ALWAYS_DENY" => GuestPolicyType.ALWAYS_DENY
case "ASK_MODERATOR" => GuestPolicyType.ASK_MODERATOR
//default
case undef => GuestPolicyType.ASK_MODERATOR
case undef => GuestPolicyType.ASK_MODERATOR
}
eventBus.publish(BigBlueButtonEvent(meetingId, new SetGuestPolicy(meetingId, policy, requesterId)))
}
@ -442,7 +456,7 @@ class BigBlueButtonInGW(
}
def voiceUserJoined(voiceConfId: String, voiceUserId: String, userId: String, callerIdName: String,
callerIdNum: String, muted: java.lang.Boolean, avatarURL: String, talking: java.lang.Boolean) {
callerIdNum: String, muted: java.lang.Boolean, avatarURL: String, talking: java.lang.Boolean) {
eventBus.publish(BigBlueButtonEvent(voiceConfId, new UserJoinedVoiceConfMessage(voiceConfId, voiceUserId, userId, userId, callerIdName,
callerIdNum, muted, talking, avatarURL, false /*hardcode listenOnly to false as the message for listenOnly is ConnectedToGlobalAudio*/ )))
}

View File

@ -50,7 +50,7 @@ object JsonMessageDecoder {
def decode(json: String): Option[InMessage] = {
unmarshall(json) match {
case Success(validMsg) => Some(validMsg)
case Failure(ex) => None
case Failure(ex) => None
}
}

View File

@ -19,16 +19,16 @@ class JsonMessageSenderActor(val service: MessageSender)
def receive = {
// Breakout
case msg: CreateBreakoutRoom => handleCreateBreakoutRoom(msg)
case msg: EndBreakoutRoom => handleEndBreakoutRoom(msg)
case msg: BreakoutRoomsListOutMessage => handleBreakoutRoomsList(msg)
case msg: CreateBreakoutRoom => handleCreateBreakoutRoom(msg)
case msg: EndBreakoutRoom => handleEndBreakoutRoom(msg)
case msg: BreakoutRoomsListOutMessage => handleBreakoutRoomsList(msg)
case msg: BreakoutRoomJoinURLOutMessage => handleBreakoutRoomJoinURL(msg)
case msg: BreakoutRoomStartedOutMessage => handleBreakoutRoomStarted(msg)
case msg: BreakoutRoomEndedOutMessage => handleBreakoutRoomEnded(msg)
case msg: BreakoutRoomEndedOutMessage => handleBreakoutRoomEnded(msg)
case msg: UpdateBreakoutUsersOutMessage => handleUpdateBreakoutUsers(msg)
case msg: MeetingTimeRemainingUpdate => handleMeetingTimeRemainingUpdate(msg)
case msg: MeetingTimeRemainingUpdate => handleMeetingTimeRemainingUpdate(msg)
case _ => // do nothing
case _ => // do nothing
}
// Breakout
@ -87,8 +87,10 @@ class JsonMessageSenderActor(val service: MessageSender)
}
def handleBreakoutRoomJoinURL(msg: BreakoutRoomJoinURLOutMessage) {
val payload = new BreakoutRoomJoinURLPayload(msg.parentMeetingId,
msg.breakoutMeetingId, msg.userId, msg.redirectJoinURL, msg.noRedirectJoinURL)
val payload = new BreakoutRoomJoinURLPayload(
msg.parentMeetingId,
msg.breakoutMeetingId, msg.userId, msg.redirectJoinURL, msg.noRedirectJoinURL
)
val request = new BreakoutRoomJoinURL(payload)
service.send(MessagingConstants.FROM_MEETING_CHANNEL, request.toJson)
}

View File

@ -5,8 +5,8 @@ import org.bigbluebutton.core.api.Permissions
case object StopMeetingActor
case class MeetingExtensionProp(maxExtensions: Int = 2, numExtensions: Int = 0, extendByMinutes: Int = 20,
sendNotice: Boolean = true, sent15MinNotice: Boolean = false,
sent10MinNotice: Boolean = false, sent5MinNotice: Boolean = false)
sendNotice: Boolean = true, sent15MinNotice: Boolean = false,
sent10MinNotice: Boolean = false, sent5MinNotice: Boolean = false)
class MeetingModel {
private var audioSettingsInited = false

View File

@ -6,15 +6,19 @@ import org.bigbluebutton.core.api.IOutMessage
import org.bigbluebutton.core.bus._
object OutMessageGatewayImp {
def apply(outgoingEventBus: OutgoingEventBus,
outBus2: OutEventBus2,
recordBus: RecordingEventBus) =
def apply(
outgoingEventBus: OutgoingEventBus,
outBus2: OutEventBus2,
recordBus: RecordingEventBus
) =
new OutMessageGatewayImp(outgoingEventBus, outBus2, recordBus)
}
class OutMessageGatewayImp(outgoingEventBus: OutgoingEventBus,
outBus2: OutEventBus2,
recordBus: RecordingEventBus) extends OutMessageGateway
class OutMessageGatewayImp(
outgoingEventBus: OutgoingEventBus,
outBus2: OutEventBus2,
recordBus: RecordingEventBus
) extends OutMessageGateway
with SystemConfiguration {
def send1(msg: IOutMessage) {

View File

@ -20,7 +20,7 @@ object UserMessagesProtocol extends DefaultJsonProtocol {
def read(json: JsValue): MessageType.MessageType = json match {
case JsString(str) => MessageType.withName(str)
case _ => throw new DeserializationException("Enum string expected")
case _ => throw new DeserializationException("Enum string expected")
}
}

View File

@ -8,6 +8,6 @@ trait OutMessage
case class CreateBreakoutRoomOutMsgEnvelope(header: OutMsgEnvelopeHeader, payload: CreateBreakoutRoomOutMsgEnvelopePayload)
case class CreateBreakoutRoomOutMsgEnvelopePayload(header: OutMsgHeader, payload: CreateBreakoutRoomOutMsgPayload)
case class CreateBreakoutRoomOutMsgPayload(meetingId: String, parentId: String, name: String,
voiceConfId: String, moderatorPassword: String, viewerPassword: String,
durationInMinutes: Int, sourcePresentationId: String, sourcePresentationSlide: Int,
record: Boolean, sequence: Int)
voiceConfId: String, moderatorPassword: String, viewerPassword: String,
durationInMinutes: Int, sourcePresentationId: String, sourcePresentationSlide: Int,
record: Boolean, sequence: Int)

View File

@ -74,9 +74,9 @@ case class GetLockSettings(meetingID: String, userId: String) extends InMessage
/////////////////////////////////////////////////////////////////////////////////
case class ValidateAuthToken(meetingID: String, userId: String, token: String,
correlationId: String, sessionId: String) extends InMessage
correlationId: String, sessionId: String) extends InMessage
case class RegisterUser(meetingID: String, userID: String, name: String, role: String,
extUserID: String, authToken: String, avatarURL: String, guest: Boolean, authed: Boolean) extends InMessage
extUserID: String, authToken: String, avatarURL: String, guest: Boolean, authed: Boolean) extends InMessage
case class UserJoining(meetingID: String, userID: String, authToken: String) extends InMessage
case class UserLeaving(meetingID: String, userID: String, sessionId: String) extends InMessage
case class GetUsers(meetingID: String, requesterID: String) extends InMessage
@ -98,9 +98,9 @@ case class LogoutEndMeeting(meetingID: String, userID: String) extends InMessage
/////////////////////////////////////////////////////////////////////////////////
case class UserConnectedToGlobalAudio(meetingID: String, /** Not used. Just to satisfy trait **/ voiceConf: String,
userid: String, name: String) extends InMessage
userid: String, name: String) extends InMessage
case class UserDisconnectedFromGlobalAudio(meetingID: String, /** Not used. Just to satisfy trait **/ voiceConf: String,
userid: String, name: String) extends InMessage
userid: String, name: String) extends InMessage
///////////////////////////////////////////////////////////////////////////////////////
// Guest support
@ -116,7 +116,7 @@ case class RespondToGuest(meetingID: String, userId: String, response: Boolean,
case class GetCurrentLayoutRequest(meetingID: String, requesterID: String) extends InMessage
case class LockLayoutRequest(meetingID: String, setById: String, lock: Boolean, viewersOnly: Boolean,
layout: Option[String]) extends InMessage
layout: Option[String]) extends InMessage
case class BroadcastLayoutRequest(meetingID: String, requesterID: String, layout: String) extends InMessage
//////////////////////////////////////////////////////////////////////////////////////
@ -127,19 +127,19 @@ case class ClearPresentation(meetingID: String) extends InMessage
case class RemovePresentation(meetingID: String, presentationID: String) extends InMessage
case class GetPresentationInfo(meetingID: String, requesterID: String, replyTo: String) extends InMessage
case class ResizeAndMoveSlide(meetingID: String, xOffset: Double, yOffset: Double,
widthRatio: Double, heightRatio: Double) extends InMessage
widthRatio: Double, heightRatio: Double) extends InMessage
case class GotoSlide(meetingID: String, page: String) extends InMessage
case class SharePresentation(meetingID: String, presentationID: String, share: Boolean) extends InMessage
case class GetSlideInfo(meetingID: String, requesterID: String, replyTo: String) extends InMessage
case class PreuploadedPresentations(meetingID: String, presentations: Seq[Presentation]) extends InMessage
case class PresentationConversionUpdate(meetingID: String, messageKey: String, code: String,
presentationId: String, presName: String) extends InMessage
presentationId: String, presName: String) extends InMessage
case class PresentationPageCountError(meetingID: String, messageKey: String, code: String, presentationId: String,
numberOfPages: Int, maxNumberPages: Int, presName: String) extends InMessage
numberOfPages: Int, maxNumberPages: Int, presName: String) extends InMessage
case class PresentationSlideGenerated(meetingID: String, messageKey: String, code: String, presentationId: String,
numberOfPages: Int, pagesCompleted: Int, presName: String) extends InMessage
numberOfPages: Int, pagesCompleted: Int, presName: String) extends InMessage
case class PresentationConversionCompleted(meetingID: String, messageKey: String, code: String,
presentation: Presentation) extends InMessage
presentation: Presentation) extends InMessage
/////////////////////////////////////////////////////////////////////////////////////
// Polling
@ -168,9 +168,9 @@ case class MuteUserRequest(meetingID: String, requesterID: String, userID: Strin
case class LockUserRequest(meetingID: String, requesterID: String, userID: String, lock: Boolean) extends InMessage
case class EjectUserFromVoiceRequest(meetingID: String, userId: String, ejectedBy: String) extends InMessage
case class VoiceUserJoinedMessage(meetingID: String, user: String, voiceConfId: String,
callerIdNum: String, callerIdName: String, muted: Boolean, talking: Boolean) extends InMessage
callerIdNum: String, callerIdName: String, muted: Boolean, talking: Boolean) extends InMessage
case class UserJoinedVoiceConfMessage(voiceConfId: String, voiceUserId: String, userId: String, externUserId: String,
callerIdName: String, callerIdNum: String, muted: Boolean, talking: Boolean, avatarURL: String, listenOnly: Boolean) extends InMessage
callerIdName: String, callerIdNum: String, muted: Boolean, talking: Boolean, avatarURL: String, listenOnly: Boolean) extends InMessage
case class UserLeftVoiceConfMessage(voiceConfId: String, voiceUserId: String) extends InMessage
case class UserLockedInVoiceConfMessage(voiceConfId: String, voiceUserId: String, locked: Boolean) extends InMessage
case class UserMutedInVoiceConfMessage(voiceConfId: String, voiceUserId: String, muted: Boolean) extends InMessage

View File

@ -10,7 +10,7 @@ case class VoiceRecordingStopped(meetingID: String, recorded: Boolean, recording
case class RecordingStatusChanged(meetingID: String, recorded: Boolean, userId: String, recording: Boolean) extends IOutMessage
case class GetRecordingStatusReply(meetingID: String, recorded: Boolean, userId: String, recording: Boolean) extends IOutMessage
case class MeetingCreated(meetingID: String, externalMeetingID: String, parentMeetingID: String, recorded: Boolean, name: String,
voiceBridge: String, duration: Int, moderatorPass: String, viewerPass: String, createTime: Long, createDate: String, isBreakout: Boolean) extends IOutMessage
voiceBridge: String, duration: Int, moderatorPass: String, viewerPass: String, createTime: Long, createDate: String, isBreakout: Boolean) extends IOutMessage
case class MeetingMuted(meetingID: String, recorded: Boolean, meetingMuted: Boolean) extends IOutMessage
case class MeetingEnding(meetingID: String) extends IOutMessage
case class MeetingEnded(meetingID: String, recorded: Boolean, voiceBridge: String) extends IOutMessage
@ -30,8 +30,8 @@ case class BreakoutRoomsListOutMessage(meetingId: String, rooms: Vector[Breakout
case class CreateBreakoutRoom(meetingId: String, room: BreakoutRoomOutPayload) extends IOutMessage
case class EndBreakoutRoom(breakoutMeetingId: String) extends IOutMessage
case class BreakoutRoomOutPayload(breakoutMeetingId: String, name: String, parentId: String, sequence: Integer,
voiceConfId: String, durationInMinutes: Int, moderatorPassword: String, viewerPassword: String,
sourcePresentationId: String, sourcePresentationSlide: Int, record: Boolean)
voiceConfId: String, durationInMinutes: Int, moderatorPassword: String, viewerPassword: String,
sourcePresentationId: String, sourcePresentationSlide: Int, record: Boolean)
case class BreakoutRoomJoinURLOutMessage(parentMeetingId: String, recorded: Boolean, breakoutMeetingId: String, userId: String, redirectJoinURL: String, noRedirectJoinURL: String) extends IOutMessage
case class BreakoutRoomStartedOutMessage(parentMeetingId: String, recorded: Boolean, breakout: BreakoutRoomInfo) extends IOutMessage
case class UpdateBreakoutUsersOutMessage(parentMeetingId: String, recorded: Boolean, breakoutMeetingId: String, users: Vector[BreakoutUserVO]) extends IOutMessage
@ -64,7 +64,7 @@ case class UserStatusChange(meetingID: String, recorded: Boolean, userID: String
case class UserRoleChange(meetingID: String, recorded: Boolean, userID: String, role: String) extends IOutMessage
case class GetUsersInVoiceConference(meetingID: String, recorded: Boolean, voiceConfId: String) extends IOutMessage
case class MuteVoiceUser(meetingID: String, recorded: Boolean, requesterID: String,
userId: String, voiceConfId: String, voiceUserId: String, mute: Boolean) extends IOutMessage
userId: String, voiceConfId: String, voiceUserId: String, mute: Boolean) extends IOutMessage
case class UserVoiceMuted(meetingID: String, recorded: Boolean, confNum: String, user: UserVO) extends IOutMessage
case class UserVoiceTalking(meetingID: String, recorded: Boolean, confNum: String, user: UserVO) extends IOutMessage
case class EjectVoiceUser(meetingID: String, recorded: Boolean, requesterID: String, userId: String, voiceConfId: String, voiceUserId: String) extends IOutMessage
@ -82,30 +82,30 @@ case class StopRecording(meetingID: String, recorded: Boolean, requesterID: Stri
// Layout
case class GetCurrentLayoutReply(meetingID: String, recorded: Boolean, requesterID: String, layoutID: String,
locked: Boolean, setByUserID: String) extends IOutMessage
locked: Boolean, setByUserID: String) extends IOutMessage
case class BroadcastLayoutEvent(meetingID: String, recorded: Boolean, requesterID: String,
layoutID: String, locked: Boolean, setByUserID: String, applyTo: Array[UserVO]) extends IOutMessage
layoutID: String, locked: Boolean, setByUserID: String, applyTo: Array[UserVO]) extends IOutMessage
case class LockLayoutEvent(meetingID: String, recorded: Boolean, setById: String, locked: Boolean,
applyTo: Array[UserVO]) extends IOutMessage
applyTo: Array[UserVO]) extends IOutMessage
// Presentation
case class ClearPresentationOutMsg(meetingID: String, recorded: Boolean) extends IOutMessage
case class RemovePresentationOutMsg(meetingID: String, recorded: Boolean, presentationID: String) extends IOutMessage
case class GetPresentationInfoOutMsg(meetingID: String, recorded: Boolean, requesterID: String,
info: CurrentPresentationInfo, replyTo: String) extends IOutMessage
info: CurrentPresentationInfo, replyTo: String) extends IOutMessage
case class ResizeAndMoveSlideOutMsg(meetingID: String, recorded: Boolean, page: Page) extends IOutMessage
case class GotoSlideOutMsg(meetingID: String, recorded: Boolean, page: Page) extends IOutMessage
case class SharePresentationOutMsg(meetingID: String, recorded: Boolean, presentation: Presentation) extends IOutMessage
case class GetSlideInfoOutMsg(meetingID: String, recorded: Boolean, requesterID: String, page: Page, replyTo: String) extends IOutMessage
case class GetPreuploadedPresentationsOutMsg(meetingID: String, recorded: Boolean) extends IOutMessage
case class PresentationConversionProgress(meetingID: String, messageKey: String, code: String,
presentationId: String, presentationName: String) extends IOutMessage
presentationId: String, presentationName: String) extends IOutMessage
case class PresentationConversionError(meetingID: String, messageKey: String, code: String,
presentationId: String, numberOfPages: Int, maxNumberPages: Int, presentationName: String) extends IOutMessage
presentationId: String, numberOfPages: Int, maxNumberPages: Int, presentationName: String) extends IOutMessage
case class PresentationPageGenerated(meetingID: String, messageKey: String, code: String, presentationId: String,
numberOfPages: Int, pagesCompleted: Int, presentationName: String) extends IOutMessage
numberOfPages: Int, pagesCompleted: Int, presentationName: String) extends IOutMessage
case class PresentationConversionDone(meetingID: String, recorded: Boolean, messageKey: String, code: String,
presentation: Presentation) extends IOutMessage
presentation: Presentation) extends IOutMessage
case class PresentationChanged(meetingID: String, presentation: Presentation) extends IOutMessage
case class GetPresentationStatusReply(meetingID: String, presentations: Seq[Presentation], current: Presentation, replyTo: String) extends IOutMessage
case class PresentationRemoved(meetingID: String, presentationId: String) extends IOutMessage

View File

@ -35,58 +35,65 @@ object ErrorCodes {
case class RequestResult(status: StatusCode, errors: Option[Array[ErrorCode]])
case class Presenter(
presenterID: String,
presenterID: String,
presenterName: String,
assignedBy: String)
assignedBy: String
)
case class User(
id: String,
externId: String,
name: String,
moderator: Boolean,
avatarUrl: String,
logoutUrl: String,
presenter: Boolean,
callerId: CallerId,
id: String,
externId: String,
name: String,
moderator: Boolean,
avatarUrl: String,
logoutUrl: String,
presenter: Boolean,
callerId: CallerId,
phoneCaller: Boolean,
emojiStatus: String,
muted: Boolean,
talking: Boolean)
muted: Boolean,
talking: Boolean
)
case class CallerId(
name: String,
number: String)
name: String,
number: String
)
case class Permissions(
disableCam: Boolean = false,
disableMic: Boolean = false,
disablePrivChat: Boolean = false,
disablePubChat: Boolean = false,
lockedLayout: Boolean = false,
lockOnJoin: Boolean = false,
lockOnJoinConfigurable: Boolean = false)
disableCam: Boolean = false,
disableMic: Boolean = false,
disablePrivChat: Boolean = false,
disablePubChat: Boolean = false,
lockedLayout: Boolean = false,
lockOnJoin: Boolean = false,
lockOnJoinConfigurable: Boolean = false
)
case class Voice(
id: String,
webId: String,
callId: CallerId,
id: String,
webId: String,
callId: CallerId,
phoningIn: Boolean,
joined: Boolean,
locked: Boolean,
muted: Boolean,
talking: Boolean)
joined: Boolean,
locked: Boolean,
muted: Boolean,
talking: Boolean
)
case class MeetingConfig(name: String,
id: MeetingID,
passwords: MeetingPasswords,
welcomeMsg: String,
logoutUrl: String,
maxUsers: Int,
record: Boolean = false,
duration: MeetingDuration,
defaultAvatarURL: String,
case class MeetingConfig(
name: String,
id: MeetingID,
passwords: MeetingPasswords,
welcomeMsg: String,
logoutUrl: String,
maxUsers: Int,
record: Boolean = false,
duration: MeetingDuration,
defaultAvatarURL: String,
defaultConfigToken: String,
guestPolicy: String = GuestPolicyType.ASK_MODERATOR)
guestPolicy: String = GuestPolicyType.ASK_MODERATOR
)
case class MeetingName(name: String)
@ -97,11 +104,12 @@ case class VoiceConfig(telVoice: String, webVoice: String, dialNumber: String)
case class MeetingPasswords(moderatorPass: String, viewerPass: String)
case class MeetingDuration(duration: Int = 0, createdTime: Long = 0,
startTime: Long = 0, endTime: Long = 0)
startTime: Long = 0, endTime: Long = 0)
case class MeetingInfo(
meetingID: String,
meetingID: String,
meetingName: String,
recorded: Boolean,
recorded: Boolean,
voiceBridge: String,
duration: Long)
duration: Long
)

View File

@ -6,11 +6,11 @@ import org.bigbluebutton.common2.domain.PageVO
case class CurrentPresenter(userId: String, name: String, assignedBy: String)
case class CurrentPresentationInfo(presenter: CurrentPresenter, presentations: Seq[Presentation])
case class Presentation(id: String, name: String, current: Boolean = false,
pages: scala.collection.immutable.Map[String, PageVO], downloadable: Boolean)
pages: scala.collection.immutable.Map[String, PageVO], downloadable: Boolean)
case class Page(id: String, num: Int, thumbUri: String = "", swfUri: String,
txtUri: String, svgUri: String, current: Boolean = false, xOffset: Double = 0, yOffset: Double = 0,
widthRatio: Double = 100D, heightRatio: Double = 100D)
txtUri: String, svgUri: String, current: Boolean = false, xOffset: Double = 0, yOffset: Double = 0,
widthRatio: Double = 100D, heightRatio: Double = 100D)
class PresentationModel {
private var presentations = new scala.collection.immutable.HashMap[String, Presentation]
@ -70,8 +70,8 @@ class PresentationModel {
}
def resizePage(presentationId: String, pageId: String,
xOffset: Double, yOffset: Double, widthRatio: Double,
heightRatio: Double): Option[PageVO] = {
xOffset: Double, yOffset: Double, widthRatio: Double,
heightRatio: Double): Option[PageVO] = {
for {
pres <- presentations.get(presentationId)
page <- pres.pages.get(pageId)

View File

@ -103,7 +103,7 @@ class SharedNotesModel {
def getNoteReport(noteId: String): Option[NoteReport] = {
notes.get(noteId) match {
case Some(note) => Some(noteToReport(note))
case None => None
case None => None
}
}

View File

@ -218,16 +218,15 @@ class WhiteboardModel {
def cleansePointsInAnnotation(ann: AnnotationVO): AnnotationVO = {
var updatedAnnotationInfo = ann.annotationInfo
ann.annotationInfo.get("points").foreach(points =>
updatedAnnotationInfo = (ann.annotationInfo + ("points" -> convertListNumbersToFloat(points.asInstanceOf[List[_]])))
)
updatedAnnotationInfo = (ann.annotationInfo + ("points" -> convertListNumbersToFloat(points.asInstanceOf[List[_]]))))
ann.copy(annotationInfo = updatedAnnotationInfo)
}
def convertListNumbersToFloat(list: List[_]): List[Float] = {
list.map {
case f: Double => f.toFloat
case f: Float => f
case f: Int => f.toFloat
case f: Float => f
case f: Int => f.toFloat
}.asInstanceOf[List[Float]]
}
}

View File

@ -51,13 +51,14 @@ object BreakoutRoomsUtil {
}
def joinParams(username: String, userId: String, isBreakout: Boolean, breakoutMeetingId: String,
password: String): (mutable.Map[String, String], mutable.Map[String, String]) = {
password: String): (mutable.Map[String, String], mutable.Map[String, String]) = {
val params = collection.mutable.HashMap(
"fullName" -> urlEncode(username),
"userID" -> urlEncode(userId),
"isBreakout" -> urlEncode(isBreakout.toString()),
"meetingID" -> urlEncode(breakoutMeetingId),
"password" -> urlEncode(password))
"password" -> urlEncode(password)
)
(params += "redirect" -> urlEncode("true"), mutable.Map[String, String]() ++= params += "redirect" -> urlEncode("false"))
}

View File

@ -61,12 +61,14 @@ trait BreakoutRoomCreatedMsgHdlr extends SystemConfiguration {
}
def sendBreakoutRoomStarted(meetingId: String, breakoutName: String, externalMeetingId: String,
breakoutMeetingId: String, sequence: Int, voiceConfId: String) {
breakoutMeetingId: String, sequence: Int, voiceConfId: String) {
log.info("Sending breakout room started {} for parent meeting {} ", breakoutMeetingId, meetingId)
def build(meetingId: String, breakout: BreakoutRoomInfo): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, "not-used")
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, "not-used"
)
val envelope = BbbCoreEnvelope(BreakoutRoomStartedEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(BreakoutRoomStartedEvtMsg.NAME, liveMeeting.props.meetingProp.intId, "not-used")
@ -97,7 +99,7 @@ trait BreakoutRoomCreatedMsgHdlr extends SystemConfiguration {
BreakoutRoomsUtil.calculateChecksum(apiCall, noRedirectBaseString, bbbWebSharedSecret))
} yield {
def build(meetingId: String, breakoutMeetingId: String,
userId: String, redirectJoinURL: String, noRedirectJoinURL: String): BbbCommonEnvCoreMsg = {
userId: String, redirectJoinURL: String, noRedirectJoinURL: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
val envelope = BbbCoreEnvelope(BreakoutRoomJoinURLEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(BreakoutRoomJoinURLEvtMsg.NAME, meetingId, "not-used")

View File

@ -14,11 +14,15 @@ trait CreateBreakoutRoomsCmdMsgHdlr {
def handleCreateBreakoutRoomsCmdMsg(msg: CreateBreakoutRoomsCmdMsg): Unit = {
// If breakout rooms are being created we ignore the coming message
if (liveMeeting.breakoutRooms.pendingRoomsNumber > 0) {
log.warning("CreateBreakoutRooms event received while {} are pending to be created for meeting {}",
liveMeeting.breakoutRooms.pendingRoomsNumber, liveMeeting.props.meetingProp.intId)
log.warning(
"CreateBreakoutRooms event received while {} are pending to be created for meeting {}",
liveMeeting.breakoutRooms.pendingRoomsNumber, liveMeeting.props.meetingProp.intId
)
} else if (BreakoutRooms.getNumberOfRooms(liveMeeting.breakoutRooms) > 0) {
log.warning("CreateBreakoutRooms event received while {} breakout rooms running for meeting {}",
BreakoutRooms.getNumberOfRooms(liveMeeting.breakoutRooms), liveMeeting.props.meetingProp.intId)
log.warning(
"CreateBreakoutRooms event received while {} breakout rooms running for meeting {}",
BreakoutRooms.getNumberOfRooms(liveMeeting.breakoutRooms), liveMeeting.props.meetingProp.intId
)
} else {
var i = 0
// in very rare cases the presentation conversion generates an error, what should we do?

View File

@ -38,8 +38,10 @@ trait RequestBreakoutJoinURLReqMsgHdlr {
val envelope = BbbCoreEnvelope(RequestBreakoutJoinURLRespMsg.NAME, routing)
val header = BbbClientMsgHeader(RequestBreakoutJoinURLRespMsg.NAME, props.meetingProp.intId, msg.header.userId)
val body = RequestBreakoutJoinURLRespMsgBody(props.meetingProp.intId,
externalMeetingId, userId, redirectJoinURL, noRedirectJoinURL)
val body = RequestBreakoutJoinURLRespMsgBody(
props.meetingProp.intId,
externalMeetingId, userId, redirectJoinURL, noRedirectJoinURL
)
val event = RequestBreakoutJoinURLRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)

View File

@ -16,7 +16,9 @@ trait SendBreakoutUsersUpdateMsgHdlr {
val users = Users2x.findAll(liveMeeting.users2x)
val breakoutUsers = users map { u => new BreakoutUserVO(u.extId, u.name) }
eventBus.publish(BigBlueButtonEvent(props.breakoutProps.parentId,
new BreakoutRoomUsersUpdate(props.breakoutProps.parentId, props.meetingProp.intId, breakoutUsers)))
eventBus.publish(BigBlueButtonEvent(
props.breakoutProps.parentId,
new BreakoutRoomUsersUpdate(props.breakoutProps.parentId, props.meetingProp.intId, breakoutUsers)
))
}
}

View File

@ -6,8 +6,10 @@ import org.bigbluebutton.common2.msgs.TranscriptVO
import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.running.LiveMeeting
class CaptionApp2x(val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway)(implicit val context: ActorContext)
class CaptionApp2x(
val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway
)(implicit val context: ActorContext)
extends UserLeavingHdlr
with EditCaptionHistoryPubMsgHdlr
with UpdateCaptionOwnerPubMsgHdlr

View File

@ -6,8 +6,10 @@ import org.bigbluebutton.common2.msgs.TranscriptVO
import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.running.LiveMeeting
class ChatApp2x(val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway)(implicit val context: ActorContext)
class ChatApp2x(
val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway
)(implicit val context: ActorContext)
extends GetChatHistoryReqMsgHdlr
with SendPublicMessagePubMsgHdlr
with SendPrivateMessagePubMsgHdlr

View File

@ -24,7 +24,8 @@ trait BroadcastLayoutMsgHdlr {
val body = BroadcastLayoutEvtMsgBody(
Layouts.getCurrentLayout(),
MeetingStatus2x.getPermissions(liveMeeting.status).lockedLayout,
Layouts.getLayoutSetter(), affectedUsers)
Layouts.getLayoutSetter(), affectedUsers
)
val event = BroadcastLayoutEvtMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)

View File

@ -20,9 +20,11 @@ trait GetCurrentLayoutReqMsgHdlr {
val envelope = BbbCoreEnvelope(GetCurrentLayoutRespMsg.NAME, routing)
val header = BbbClientMsgHeader(GetCurrentLayoutRespMsg.NAME, liveMeeting.props.meetingProp.intId, msg.header.userId)
val body = GetCurrentLayoutRespMsgBody(Layouts.getCurrentLayout(),
val body = GetCurrentLayoutRespMsgBody(
Layouts.getCurrentLayout(),
MeetingStatus2x.getPermissions(liveMeeting.status).lockedLayout,
Layouts.getLayoutSetter())
Layouts.getLayoutSetter()
)
val event = GetCurrentLayoutRespMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)

View File

@ -8,8 +8,10 @@ import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.common2.domain.PageVO
import org.bigbluebutton.core.apps.Presentation
class PresentationApp2x(val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway)(implicit val context: ActorContext)
class PresentationApp2x(
val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway
)(implicit val context: ActorContext)
extends NewPresentationMsgHdlr
with SetCurrentPresentationPubMsgHdlr
with GetPresentationInfoReqMsgHdlr
@ -54,8 +56,8 @@ class PresentationApp2x(val liveMeeting: LiveMeeting,
}
def resizeAndMovePage(presentationId: String, pageId: String,
xOffset: Double, yOffset: Double, widthRatio: Double,
heightRatio: Double): Option[PageVO] = {
xOffset: Double, yOffset: Double, widthRatio: Double,
heightRatio: Double): Option[PageVO] = {
// Force coordinate that are out-of-bounds inside valid values
// 0.25D is 400% zoom
// 100D-checkedWidth is the maximum the page can be moved over

View File

@ -5,8 +5,10 @@ import akka.event.Logging
import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.running.LiveMeeting
class ScreenshareApp2x(val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway)(implicit val context: ActorContext)
class ScreenshareApp2x(
val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway
)(implicit val context: ActorContext)
extends ScreenshareStartedVoiceConfEvtMsgHdlr
with ScreenshareStoppedVoiceConfEvtMsgHdlr
with ScreenshareRtmpBroadcastStartedVoiceConfEvtMsgHdlr

View File

@ -11,13 +11,17 @@ trait ScreenshareRtmpBroadcastStartedVoiceConfEvtMsgHdlr {
def handleScreenshareRtmpBroadcastStartedVoiceConfEvtMsg(msg: ScreenshareRtmpBroadcastStartedVoiceConfEvtMsg): Unit = {
def broadcastEvent(voiceConf: String, screenshareConf: String, stream: String, vidWidth: Int, vidHeight: Int,
timestamp: String): BbbCommonEnvCoreMsg = {
timestamp: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, "not-used")
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, "not-used"
)
val envelope = BbbCoreEnvelope(ScreenshareRtmpBroadcastStartedEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(ScreenshareRtmpBroadcastStartedEvtMsg.NAME,
liveMeeting.props.meetingProp.intId, "not-used")
val header = BbbClientMsgHeader(
ScreenshareRtmpBroadcastStartedEvtMsg.NAME,
liveMeeting.props.meetingProp.intId, "not-used"
)
val body = ScreenshareRtmpBroadcastStartedEvtMsgBody(voiceConf, screenshareConf,
stream, vidWidth, vidHeight, timestamp)

View File

@ -12,14 +12,18 @@ trait ScreenshareRtmpBroadcastStoppedVoiceConfEvtMsgHdlr {
def handleScreenshareRtmpBroadcastStoppedVoiceConfEvtMsg(msg: ScreenshareRtmpBroadcastStoppedVoiceConfEvtMsg): Unit = {
def broadcastEvent(voiceConf: String, screenshareConf: String,
stream: String, vidWidth: Int, vidHeight: Int,
timestamp: String): BbbCommonEnvCoreMsg = {
stream: String, vidWidth: Int, vidHeight: Int,
timestamp: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, "not-used")
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, "not-used"
)
val envelope = BbbCoreEnvelope(ScreenshareRtmpBroadcastStoppedEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(ScreenshareRtmpBroadcastStoppedEvtMsg.NAME,
liveMeeting.props.meetingProp.intId, "not-used")
val header = BbbClientMsgHeader(
ScreenshareRtmpBroadcastStoppedEvtMsg.NAME,
liveMeeting.props.meetingProp.intId, "not-used"
)
val body = ScreenshareRtmpBroadcastStoppedEvtMsgBody(voiceConf, screenshareConf,
stream, vidWidth, vidHeight, timestamp)

View File

@ -15,8 +15,10 @@ trait ScreenshareStartedVoiceConfEvtMsgHdlr {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(ScreenshareStartRtmpBroadcastVoiceConfMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(ScreenshareStartRtmpBroadcastVoiceConfMsg.NAME,
liveMeeting.props.meetingProp.intId)
val header = BbbCoreHeaderWithMeetingId(
ScreenshareStartRtmpBroadcastVoiceConfMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = ScreenshareStartRtmpBroadcastVoiceConfMsgBody(voiceConf: String, screenshareConf: String, url: String, timestamp: String)
val event = ScreenshareStartRtmpBroadcastVoiceConfMsg(header, body)

View File

@ -14,8 +14,10 @@ trait ScreenshareStoppedVoiceConfEvtMsgHdlr {
def broadcastEvent(voiceConf: String, screenshareConf: String, url: String, timestamp: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(ScreenshareStopRtmpBroadcastVoiceConfMsg.NAME, routing)
val header = BbbCoreHeaderWithMeetingId(ScreenshareStopRtmpBroadcastVoiceConfMsg.NAME,
liveMeeting.props.meetingProp.intId)
val header = BbbCoreHeaderWithMeetingId(
ScreenshareStopRtmpBroadcastVoiceConfMsg.NAME,
liveMeeting.props.meetingProp.intId
)
val body = ScreenshareStopRtmpBroadcastVoiceConfMsgBody(voiceConf, screenshareConf, url, timestamp)
val event = ScreenshareStopRtmpBroadcastVoiceConfMsg(header, body)

View File

@ -5,8 +5,10 @@ import akka.event.Logging
import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.running.LiveMeeting
class SharedNotesApp2x(val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway)(implicit val context: ActorContext)
class SharedNotesApp2x(
val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway
)(implicit val context: ActorContext)
extends GetSharedNotesPubMsgHdlr
with SyncSharedNotePubMsgHdlr
with UpdateSharedNoteReqMsgHdlr

View File

@ -23,7 +23,7 @@ trait SyncSharedNotePubMsgHdlr {
liveMeeting.notesModel.getNoteReport(msg.body.noteId) match {
case Some(noteReport) => broadcastEvent(msg, noteReport)
case None => log.warning("Could not find note " + msg.body.noteId)
case None => log.warning("Could not find note " + msg.body.noteId)
}
}
}

View File

@ -23,9 +23,9 @@ trait UpdateSharedNoteReqMsgHdlr {
val userId = msg.body.operation match {
case "PATCH" => msg.header.userId
case "UNDO" => liveMeeting.notesModel.SYSTEM_ID
case "REDO" => liveMeeting.notesModel.SYSTEM_ID
case _ => return
case "UNDO" => liveMeeting.notesModel.SYSTEM_ID
case "REDO" => liveMeeting.notesModel.SYSTEM_ID
case _ => return
}
val (patchId, patch, undo, redo) = liveMeeting.notesModel.patchNote(msg.body.noteId, msg.body.patch, msg.body.operation)

View File

@ -10,8 +10,10 @@ trait AssignPresenterReqMsgHdlr {
def broadcastPresenterChange(oldPres: UserState, newPres: UserState): Unit = {
// unassign old presenter
val routingUnassign = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING,
this.liveMeeting.props.meetingProp.intId, oldPres.intId)
val routingUnassign = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
this.liveMeeting.props.meetingProp.intId, oldPres.intId
)
val envelopeUnassign = BbbCoreEnvelope(PresenterUnassignedEvtMsg.NAME, routingUnassign)
val headerUnassign = BbbClientMsgHeader(PresenterUnassignedEvtMsg.NAME, this.liveMeeting.props.meetingProp.intId,
oldPres.intId)
@ -22,8 +24,10 @@ trait AssignPresenterReqMsgHdlr {
outGW.send(msgEventUnassign)
// set new presenter
val routingAssign = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING,
this.liveMeeting.props.meetingProp.intId, newPres.intId)
val routingAssign = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
this.liveMeeting.props.meetingProp.intId, newPres.intId
)
val envelopeAssign = BbbCoreEnvelope(PresenterAssignedEvtMsg.NAME, routingAssign)
val headerAssign = BbbClientMsgHeader(PresenterAssignedEvtMsg.NAME, this.liveMeeting.props.meetingProp.intId,
newPres.intId)

View File

@ -19,8 +19,10 @@ trait EjectUserFromMeetingCmdMsgHdlr {
RegisteredUsers.remove(msg.body.userId, liveMeeting.registeredUsers)
// send a message to client
val ejectFromMeetingClientEvent = MsgBuilder.buildUserEjectedFromMeetingEvtMsg(liveMeeting.props.meetingProp.intId,
user.intId, msg.body.ejectedBy)
val ejectFromMeetingClientEvent = MsgBuilder.buildUserEjectedFromMeetingEvtMsg(
liveMeeting.props.meetingProp.intId,
user.intId, msg.body.ejectedBy
)
outGW.send(ejectFromMeetingClientEvent)
log.info("Ejecting user from meeting (client msg). meetingId=" + liveMeeting.props.meetingProp.intId +
" userId=" + msg.body.userId)
@ -39,8 +41,10 @@ trait EjectUserFromMeetingCmdMsgHdlr {
for {
vu <- VoiceUsers.findWithIntId(liveMeeting.voiceUsers, msg.body.userId)
} yield {
val ejectFromVoiceEvent = MsgBuilder.buildEjectUserFromVoiceConfSysMsg(liveMeeting.props.meetingProp.intId,
liveMeeting.props.voiceProp.voiceConf, vu.voiceUserId)
val ejectFromVoiceEvent = MsgBuilder.buildEjectUserFromVoiceConfSysMsg(
liveMeeting.props.meetingProp.intId,
liveMeeting.props.voiceProp.voiceConf, vu.voiceUserId
)
outGW.send(ejectFromVoiceEvent)
log.info("Ejecting user from voice. meetingId=" + liveMeeting.props.meetingProp.intId + " userId=" + vu.intId)
}

View File

@ -0,0 +1,17 @@
package org.bigbluebutton.core.apps.users
import akka.actor.ActorContext
import akka.event.Logging
import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core2.message.handlers.users.ValidateAuthTokenReqMsgHdlr
class UsersApp(
val liveMeeting: LiveMeeting,
val outGW: OutMessageGateway
)(implicit val context: ActorContext)
extends ValidateAuthTokenReqMsgHdlr {
val log = Logging(context.system, getClass)
}

View File

@ -7,7 +7,6 @@ trait UsersApp2x
extends RegisterUserReqMsgHdlr
with ChangeUserRoleCmdMsgHdlr
with SyncGetUsersMeetingRespMsgHdlr
with ValidateAuthTokenReqMsgHdlr
with UserLeaveReqMsgHdlr
with LogoutAndEndMeetingCmdMsgHdlr
with MeetingActivityResponseCmdMsgHdlr

View File

@ -17,11 +17,15 @@ trait UserJoinedVoiceConfEvtMsgHdlr {
log.warning("Received user joined voice conference " + msg)
def broadcastEvent(voiceUserState: VoiceUserState): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, voiceUserState.intId)
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, voiceUserState.intId
)
val envelope = BbbCoreEnvelope(UserJoinedVoiceConfToClientEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(UserJoinedVoiceConfToClientEvtMsg.NAME,
liveMeeting.props.meetingProp.intId, voiceUserState.intId)
val header = BbbClientMsgHeader(
UserJoinedVoiceConfToClientEvtMsg.NAME,
liveMeeting.props.meetingProp.intId, voiceUserState.intId
)
val body = UserJoinedVoiceConfToClientEvtMsgBody(intId = voiceUserState.intId, voiceUserId = voiceUserState.voiceUserId,
callerName = voiceUserState.callerName, callerNum = voiceUserState.callerNum, muted = voiceUserState.muted,

View File

@ -46,8 +46,10 @@ trait UserLeftVoiceConfEvtMsgHdlr {
log.info("Send STOP RECORDING voice conf. meetingId=" + liveMeeting.props.meetingProp.intId
+ " voice conf=" + liveMeeting.props.voiceProp.voiceConf)
val event = buildStopRecordingVoiceConfSysMsg(liveMeeting.props.meetingProp.intId,
liveMeeting.props.voiceProp.voiceConf, MeetingStatus2x.getVoiceRecordingFilename(liveMeeting.status))
val event = buildStopRecordingVoiceConfSysMsg(
liveMeeting.props.meetingProp.intId,
liveMeeting.props.voiceProp.voiceConf, MeetingStatus2x.getVoiceRecordingFilename(liveMeeting.status)
)
outGW.send(event)
}
}

View File

@ -14,12 +14,16 @@ trait UserMutedInVoiceConfEvtMsgHdlr {
def handleUserMutedInVoiceConfEvtMsg(msg: UserMutedInVoiceConfEvtMsg): Unit = {
def broadcastEvent(vu: VoiceUserState): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING,
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId,
vu.intId)
vu.intId
)
val envelope = BbbCoreEnvelope(UserMutedVoiceEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(UserMutedVoiceEvtMsg.NAME,
liveMeeting.props.meetingProp.intId, vu.intId)
val header = BbbClientMsgHeader(
UserMutedVoiceEvtMsg.NAME,
liveMeeting.props.meetingProp.intId, vu.intId
)
val body = UserMutedVoiceEvtMsgBody(intId = vu.intId, voiceUserId = vu.intId, vu.muted)

View File

@ -14,12 +14,16 @@ trait UserTalkingInVoiceConfEvtMsgHdlr {
def handleUserTalkingInVoiceConfEvtMsg(msg: UserTalkingInVoiceConfEvtMsg): Unit = {
def broadcastEvent(vu: VoiceUserState): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING,
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId,
vu.intId)
vu.intId
)
val envelope = BbbCoreEnvelope(UserTalkingVoiceEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(UserTalkingVoiceEvtMsg.NAME,
liveMeeting.props.meetingProp.intId, vu.intId)
val header = BbbClientMsgHeader(
UserTalkingVoiceEvtMsg.NAME,
liveMeeting.props.meetingProp.intId, vu.intId
)
val body = UserTalkingVoiceEvtMsgBody(intId = vu.intId, voiceUserId = vu.intId, vu.talking)

View File

@ -0,0 +1,16 @@
package org.bigbluebutton.core.bus
import akka.actor.ActorRef
class InMsgBusGW(bus: IncomingEventBusImp) extends IncomingEventBus {
override def publish(event: BigBlueButtonEvent): Unit = {
bus.publish(event)
}
override def subscribe(actorRef: ActorRef, topic: String): Unit = {
bus.subscribe(actorRef, topic)
}
override def unsubscribe(actorRef: ActorRef, topic: String): Unit = {
bus.unsubscribe(actorRef, topic)
}
}

View File

@ -1,33 +1,14 @@
package org.bigbluebutton.core.bus
import akka.actor.ActorRef
import akka.event.EventBus
import akka.event.LookupClassification
import org.bigbluebutton.core.api.InMessage
case class BigBlueButtonEvent(val topic: String, val payload: InMessage)
class IncomingEventBus extends EventBus with LookupClassification {
type Event = BigBlueButtonEvent
type Classifier = String
type Subscriber = ActorRef
trait IncomingEventBus {
// is used for extracting the classifier from the incoming events
override protected def classify(event: Event): Classifier = event.topic
// will be invoked for each event for all subscribers which registered themselves
// for the events classifier
override protected def publish(event: Event, subscriber: Subscriber): Unit = {
subscriber ! event.payload
}
// must define a full order over the subscribers, expressed as expected from
// `java.lang.Comparable.compare`
override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int =
a.compareTo(b)
// determines the initial size of the index data structure
// used internally (i.e. the expected number of different classifiers)
override protected def mapSize: Int = 128
def publish(event: BigBlueButtonEvent): Unit
def subscribe(actorRef: ActorRef, topic: String)
def unsubscribe(actorRef: ActorRef, topic: String)
}

View File

@ -0,0 +1,30 @@
package org.bigbluebutton.core.bus
import akka.actor.ActorRef
import akka.event.EventBus
import akka.event.LookupClassification
class IncomingEventBusImp extends EventBus with LookupClassification {
type Event = BigBlueButtonEvent
type Classifier = String
type Subscriber = ActorRef
// is used for extracting the classifier from the incoming events
override protected def classify(event: Event): Classifier = event.topic
// will be invoked for each event for all subscribers which registered themselves
// for the events classifier
override protected def publish(event: Event, subscriber: Subscriber): Unit = {
subscriber ! event.payload
}
// must define a full order over the subscribers, expressed as expected from
// `java.lang.Comparable.compare`
override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int =
a.compareTo(b)
// determines the initial size of the index data structure
// used internally (i.e. the expected number of different classifiers)
override protected def mapSize: Int = 128
}

View File

@ -0,0 +1,11 @@
package org.bigbluebutton.core.domain
case class MeetingInactivityTracker(
maxInactivityTimeoutMinutes: Int,
warningMinutesBeforeMax: Int,
lastActivityTime: Long,
warningSent: Boolean,
warningSentOn: Long
)
case class MeetingExpiryTracker(lastUserLeftOn: Long)

View File

@ -4,71 +4,80 @@ import com.softwaremill.quicklens._
import org.bigbluebutton.core.api.Permissions
case class MeetingProperties(
id: String,
extId: String,
name: String,
recorded: Boolean,
voiceConf: String,
duration: Int,
autoStartRecording: Boolean,
id: String,
extId: String,
name: String,
recorded: Boolean,
voiceConf: String,
duration: Int,
autoStartRecording: Boolean,
allowStartStopRecording: Boolean,
moderatorPass: String,
viewerPass: String,
createTime: Long,
createDate: String,
isBreakout: Boolean)
moderatorPass: String,
viewerPass: String,
createTime: Long,
createDate: String,
isBreakout: Boolean
)
case class MeetingProperties2x(
id: String,
extId: String,
name: String,
voiceConf: String,
duration: Int,
maxUsers: Int,
id: String,
extId: String,
name: String,
voiceConf: String,
duration: Int,
maxUsers: Int,
allowVoiceOnly: Boolean,
isBreakout: Boolean,
extensionProp: MeetingExtensionProp,
recordingProp: MeetingRecordingProp)
isBreakout: Boolean,
extensionProp: MeetingExtensionProp,
recordingProp: MeetingRecordingProp
)
case class MeetingRecordingProp(
recorded: Boolean = false,
autoStartRecording: Boolean = false,
allowStartStopRecording: Boolean = true)
recorded: Boolean = false,
autoStartRecording: Boolean = false,
allowStartStopRecording: Boolean = true
)
case class MeetingExtensionProp(
maxExtensions: Int = 0,
extendByMinutes: Int = 20,
sendNotice: Boolean = true)
maxExtensions: Int = 0,
extendByMinutes: Int = 20,
sendNotice: Boolean = true
)
case class MeetingRecordingStatus(
recording: Boolean = false,
voiceRecordingFilename: String = "")
recording: Boolean = false,
voiceRecordingFilename: String = ""
)
case class MeetingExtensionStatus(
numExtensions: Int = 0,
numExtensions: Int = 0,
sent15MinNotice: Boolean = false,
sent10MinNotice: Boolean = false,
sent5MinNotice: Boolean = false)
sent5MinNotice: Boolean = false
)
case class Meeting3x(permissions: Permissions,
isRecording: Boolean = false,
muted: Boolean = false,
ended: Boolean = false,
hasLastWebUserLeft: Boolean = false,
lastWebUserLeftOnTimestamp: Long = 0L,
voiceRecordingFilename: String = "",
startedOn: Long = 0L,
pinNumbers: Set[String] = Set.empty,
lastGeneratedPin: Int = 0,
breakoutRoomsStartedOn: Long = 0L,
breakoutRoomsDurationInMinutes: Int = 120,
extensionStatus: MeetingExtensionStatus = new MeetingExtensionStatus,
recordingStatus: MeetingRecordingStatus = new MeetingRecordingStatus)
case class Meeting3x(
permissions: Permissions,
isRecording: Boolean = false,
muted: Boolean = false,
ended: Boolean = false,
hasLastWebUserLeft: Boolean = false,
lastWebUserLeftOnTimestamp: Long = 0L,
voiceRecordingFilename: String = "",
startedOn: Long = 0L,
pinNumbers: Set[String] = Set.empty,
lastGeneratedPin: Int = 0,
breakoutRoomsStartedOn: Long = 0L,
breakoutRoomsDurationInMinutes: Int = 120,
extensionStatus: MeetingExtensionStatus = new MeetingExtensionStatus,
recordingStatus: MeetingRecordingStatus = new MeetingRecordingStatus
)
object Meeting3x {
def isExtensionAllowed(
extension: MeetingExtensionProp,
status: MeetingExtensionStatus): Boolean = status.numExtensions < extension.maxExtensions
status: MeetingExtensionStatus
): Boolean = status.numExtensions < extension.maxExtensions
def incNumExtension(extension: MeetingExtensionProp, status: MeetingExtensionStatus): MeetingExtensionStatus = {
if (status.numExtensions < extension.maxExtensions) {

View File

@ -18,8 +18,10 @@ object Util {
header
}
def buildJson(header: java.util.HashMap[String, Any],
payload: java.util.HashMap[String, Any]): String = {
def buildJson(
header: java.util.HashMap[String, Any],
payload: java.util.HashMap[String, Any]
): String = {
val message = new java.util.HashMap[String, java.util.HashMap[String, Any]]()
message.put(Constants.HEADER, header)

View File

@ -10,7 +10,7 @@ object BreakoutRooms {
def breakoutRoomsdurationInMinutes(status: BreakoutRooms, duration: Int) = status.breakoutRoomsdurationInMinutes = duration
def newBreakoutRoom(parentRoomId: String, id: String, externalMeetingId: String, name: String, sequence: Integer, voiceConfId: String,
assignedUsers: Vector[String], breakoutRooms: BreakoutRooms): Option[BreakoutRoomVO] = {
assignedUsers: Vector[String], breakoutRooms: BreakoutRooms): Option[BreakoutRoomVO] = {
val brvo = new BreakoutRoomVO(id, externalMeetingId, name, parentRoomId, sequence, voiceConfId, assignedUsers, Vector())
breakoutRooms.add(brvo)
Some(brvo)

View File

@ -101,7 +101,7 @@ object Polls {
}
def handleRespondToPollReqMsg(requesterId: String, pollId: String, questionId: Int, answerId: Int,
lm: LiveMeeting): Option[(String, String, SimplePollResultOutVO)] = {
lm: LiveMeeting): Option[(String, String, SimplePollResultOutVO)] = {
for {
curPres <- Users2x.findPresenter(lm.users2x)
@ -114,7 +114,7 @@ object Polls {
}
def handleStartCustomPollReqMsg(requesterId: String, pollId: String, pollType: String,
answers: Seq[String], lm: LiveMeeting): Option[SimplePollOutVO] = {
answers: Seq[String], lm: LiveMeeting): Option[SimplePollOutVO] = {
def createPoll(pollId: String, numRespondents: Int): Option[Poll] = {
for {
@ -142,7 +142,7 @@ object Polls {
// Helper methods:
//
private def handleRespondToPoll(poll: SimplePollResultOutVO, requesterId: String, pollId: String, questionId: Int,
answerId: Int, lm: LiveMeeting): Option[SimplePollResultOutVO] = {
answerId: Int, lm: LiveMeeting): Option[SimplePollResultOutVO] = {
/*
* Hardcode to zero as we are assuming the poll has only one question.
* Our data model supports multiple question polls but for this

View File

@ -5,8 +5,8 @@ import com.softwaremill.quicklens._
object RegisteredUsers {
def create(userId: String, extId: String, name: String, roles: String,
token: String, avatar: String, guest: Boolean, authenticated: Boolean,
waitingForAcceptance: Boolean, users: RegisteredUsers): RegisteredUser = {
token: String, avatar: String, guest: Boolean, authenticated: Boolean,
waitingForAcceptance: Boolean, users: RegisteredUsers): RegisteredUser = {
val ru = new RegisteredUser(userId, extId, name, roles, token, avatar, guest, authenticated, waitingForAcceptance)
users.save(ru)
ru
@ -48,7 +48,7 @@ object RegisteredUsers {
}
def setWaitingForApproval(users: RegisteredUsers, user: RegisteredUser,
waitingForApproval: Boolean): RegisteredUser = {
waitingForApproval: Boolean): RegisteredUser = {
val u = user.modify(_.waitingForAcceptance).setTo(waitingForApproval)
users.save(u)
u
@ -74,6 +74,6 @@ class RegisteredUsers {
}
case class RegisteredUser(id: String, externId: String, name: String, role: String,
authToken: String, avatarURL: String, guest: Boolean,
authed: Boolean, waitingForAcceptance: Boolean)
authToken: String, avatarURL: String, guest: Boolean,
authed: Boolean, waitingForAcceptance: Boolean)

View File

@ -88,7 +88,7 @@ object Users2x {
def hasPresenter(users: Users2x): Boolean = {
findPresenter(users) match {
case Some(p) => true
case None => false
case None => false
}
}
@ -144,8 +144,8 @@ class Users2x {
}
case class UserState(intId: String, extId: String, name: String, role: String,
guest: Boolean, authed: Boolean, waitingForAcceptance: Boolean, emoji: String, locked: Boolean,
presenter: Boolean, avatar: String)
guest: Boolean, authed: Boolean, waitingForAcceptance: Boolean, emoji: String, locked: Boolean,
presenter: Boolean, avatar: String)
case class UserIdAndName(id: String, name: String)

View File

@ -5,17 +5,19 @@ case class Status(isPresenter: Boolean = false, emojiStatus: String = "none")
case class CallerId(num: String = "", name: String = "")
case class Voice(
hasJoined: Boolean = false,
id: String = "",
callerId: CallerId = CallerId(),
muted: Boolean = false,
talking: Boolean = false,
locked: Boolean = false)
hasJoined: Boolean = false,
id: String = "",
callerId: CallerId = CallerId(),
muted: Boolean = false,
talking: Boolean = false,
locked: Boolean = false
)
case class UserV(
id: String,
extId: String,
name: String,
role: String = Roles.VIEWER_ROLE,
id: String,
extId: String,
name: String,
role: String = Roles.VIEWER_ROLE,
status: Status = Status(),
voice: Voice = Voice())
voice: Voice = Voice()
)

View File

@ -118,8 +118,8 @@ class VoiceUsers {
case class VoiceUser2x(intId: String, voiceUserId: String)
case class VoiceUserVO2x(intId: String, voiceUserId: String, callerName: String,
callerNum: String, joined: Boolean, locked: Boolean, muted: Boolean,
talking: Boolean, callingWith: String, listenOnly: Boolean)
callerNum: String, joined: Boolean, locked: Boolean, muted: Boolean,
talking: Boolean, callingWith: String, listenOnly: Boolean)
case class VoiceUserState(intId: String, voiceUserId: String, callingWith: String, callerName: String,
callerNum: String, muted: Boolean, talking: Boolean, listenOnly: Boolean)
callerNum: String, muted: Boolean, talking: Boolean, listenOnly: Boolean)

View File

@ -14,8 +14,9 @@ object ReceivedJsonMsgHandlerActor {
}
class ReceivedJsonMsgHandlerActor(
val eventBus: BbbMsgRouterEventBus,
val incomingJsonMessageBus: IncomingJsonMessageBus)
val eventBus: BbbMsgRouterEventBus,
val incomingJsonMessageBus: IncomingJsonMessageBus
)
extends Actor with ActorLogging
with SystemConfiguration
with ReceivedJsonMsgDeserializer

View File

@ -0,0 +1,55 @@
package org.bigbluebutton.core.running
import org.bigbluebutton.common2.domain.DefaultProps
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.api.BreakoutRoomCreated
import org.bigbluebutton.core.bus.{ BigBlueButtonEvent, IncomingEventBus }
trait AuditHelpers {
def getUsersInVoiceConf(
props: DefaultProps,
outGW: OutMessageGateway
): Unit = {
def buildGetUsersInVoiceConfSysMsg(meetingId: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(GetUsersInVoiceConfSysMsg.NAME, routing)
val body = GetUsersInVoiceConfSysMsgBody(props.voiceProp.voiceConf)
val header = BbbCoreHeaderWithMeetingId(GetUsersInVoiceConfSysMsg.NAME, meetingId)
val event = GetUsersInVoiceConfSysMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
val event = buildGetUsersInVoiceConfSysMsg(props.meetingProp.intId)
outGW.send(event)
}
def sendBreakoutRoomCreatedToParent(
props: DefaultProps,
eventBus: IncomingEventBus
): Unit = {
eventBus.publish(BigBlueButtonEvent(
props.breakoutProps.parentId,
BreakoutRoomCreated(props.breakoutProps.parentId, props.meetingProp.intId)
))
}
def sendMeetingIsActive(props: DefaultProps, outGW: OutMessageGateway): Unit = {
def buildMeetingIsActiveEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
val envelope = BbbCoreEnvelope(MeetingIsActiveEvtMsg.NAME, routing)
val body = MeetingIsActiveEvtMsgBody(meetingId)
val header = BbbClientMsgHeader(MeetingIsActiveEvtMsg.NAME, meetingId, "not-used")
val event = MeetingIsActiveEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
val event = buildMeetingIsActiveEvtMsg(props.meetingProp.intId)
outGW.send(event)
}
}

View File

@ -8,26 +8,29 @@ import org.bigbluebutton.core2.MeetingStatus2x
import org.bigbluebutton.core2.message.senders.{ MsgBuilder, Sender, UserJoinedMeetingEvtMsgBuilder }
trait HandlerHelpers {
// this: BaseMeetingActor =>
def validateTokenFailed(outGW: OutMessageGateway, meetingId: String, userId: String, authToken: String,
valid: Boolean, waitForApproval: Boolean): Unit = {
val event = MsgBuilder.buildValidateAuthTokenRespMsg(meetingId,
userId, authToken, valid, waitForApproval)
valid: Boolean, waitForApproval: Boolean): Unit = {
val event = MsgBuilder.buildValidateAuthTokenRespMsg(
meetingId,
userId, authToken, valid, waitForApproval
)
Sender.send(outGW, event)
// TODO: Should disconnect user here.
}
def sendValidateAuthTokenRespMsg(outGW: OutMessageGateway, meetingId: String, userId: String, authToken: String,
valid: Boolean, waitForApproval: Boolean): Unit = {
val event = MsgBuilder.buildValidateAuthTokenRespMsg(meetingId,
userId, authToken, valid, waitForApproval)
valid: Boolean, waitForApproval: Boolean): Unit = {
val event = MsgBuilder.buildValidateAuthTokenRespMsg(
meetingId,
userId, authToken, valid, waitForApproval
)
Sender.send(outGW, event)
}
def userValidatedButNeedToWaitForApproval(outGW: OutMessageGateway, liveMeeting: LiveMeeting,
user: RegisteredUser): Unit = {
user: RegisteredUser): Unit = {
val meetingId = liveMeeting.props.meetingProp.intId
sendValidateAuthTokenRespMsg(outGW, meetingId, user.id, user.authToken, valid = true, waitForApproval = false)
@ -40,8 +43,11 @@ trait HandlerHelpers {
GuestsWaiting.add(guestsWaitingList, guest)
}
def userValidatedAndNoNeedToWaitForApproval(outGW: OutMessageGateway, liveMeeting: LiveMeeting,
user: RegisteredUser): Unit = {
def userValidatedAndNoNeedToWaitForApproval(
outGW: OutMessageGateway,
liveMeeting: LiveMeeting,
user: RegisteredUser
): Unit = {
println("**************** userValidatedAndNoNeedToWaitForApproval")
@ -95,8 +101,8 @@ trait HandlerHelpers {
}
def sendAllVoiceUsersInMeeting(outGW: OutMessageGateway, requesterId: String,
voiceUsers: VoiceUsers,
meetingId: String): Unit = {
voiceUsers: VoiceUsers,
meetingId: String): Unit = {
val vu = VoiceUsers.findAll(voiceUsers).map { u =>
VoiceConfUser(intId = u.intId, voiceUserId = u.voiceUserId, callingWith = u.callingWith, callerName = u.callerName,
@ -111,7 +117,8 @@ trait HandlerHelpers {
for {
regUser <- RegisteredUsers.findWithToken(authToken, liveMeeting.registeredUsers)
} yield {
val userState = UserState(intId = regUser.id,
val userState = UserState(
intId = regUser.id,
extId = regUser.externId,
name = regUser.name,
role = regUser.role,
@ -121,7 +128,8 @@ trait HandlerHelpers {
emoji = "none",
presenter = false,
locked = false,
avatar = regUser.avatarURL)
avatar = regUser.avatarURL
)
Users2x.add(liveMeeting.users2x, userState)

View File

@ -9,24 +9,26 @@ import org.bigbluebutton.core.domain.Meeting3x
import org.bigbluebutton.core.models._
import org.bigbluebutton.core2.MeetingStatus2x
class LiveMeeting(val props: DefaultProps,
val status: MeetingStatus2x,
class LiveMeeting(
val props: DefaultProps,
val status: MeetingStatus2x,
val screenshareModel: ScreenshareModel,
val chatModel: ChatModel,
val layoutModel: LayoutModel,
val layouts: Layouts,
val registeredUsers: RegisteredUsers,
val polls: Polls, // 2x
val pollModel: PollModel, // 1.1x
val wbModel: WhiteboardModel,
val presModel: PresentationModel,
val breakoutRooms: BreakoutRooms,
val captionModel: CaptionModel,
val notesModel: SharedNotesModel,
val webcams: Webcams,
val voiceUsers: VoiceUsers,
val users2x: Users2x,
val guestsWaiting: GuestsWaiting) {
val chatModel: ChatModel,
val layoutModel: LayoutModel,
val layouts: Layouts,
val registeredUsers: RegisteredUsers,
val polls: Polls, // 2x
val pollModel: PollModel, // 1.1x
val wbModel: WhiteboardModel,
val presModel: PresentationModel,
val breakoutRooms: BreakoutRooms,
val captionModel: CaptionModel,
val notesModel: SharedNotesModel,
val webcams: Webcams,
val voiceUsers: VoiceUsers,
val users2x: Users2x,
val guestsWaiting: GuestsWaiting
) {
def hasMeetingEnded(): Boolean = {
MeetingStatus2x.hasMeetingEnded(status)

View File

@ -1,6 +1,9 @@
package org.bigbluebutton.core.running
import java.io.{ PrintWriter, StringWriter }
import org.bigbluebutton.core.apps.users.UsersApp
import org.bigbluebutton.core.domain.MeetingInactivityTracker
//import java.util.concurrent.TimeUnit
import akka.actor._
@ -33,16 +36,21 @@ import org.bigbluebutton.core.apps.layout.LayoutApp2x
import org.bigbluebutton.core.apps.meeting.SyncGetMeetingInfoRespMsgHdlr
object MeetingActor {
def props(props: DefaultProps,
eventBus: IncomingEventBus,
outGW: OutMessageGateway, liveMeeting: LiveMeeting): Props =
def props(
props: DefaultProps,
eventBus: IncomingEventBus,
outGW: OutMessageGateway,
liveMeeting: LiveMeeting
): Props =
Props(classOf[MeetingActor], props, eventBus, outGW, liveMeeting)
}
class MeetingActor(val props: DefaultProps,
val eventBus: IncomingEventBus,
val outGW: OutMessageGateway,
val liveMeeting: LiveMeeting)
class MeetingActor(
val props: DefaultProps,
val eventBus: IncomingEventBus,
val outGW: OutMessageGateway,
val liveMeeting: LiveMeeting
)
extends BaseMeetingActor
with GuestsApp
with LayoutApp2x
@ -83,19 +91,19 @@ class MeetingActor(val props: DefaultProps,
* Put the internal message injector into another actor so this
* actor is easy to test.
*/
var actorMonitor = context.actorOf(MeetingActorInternal.props(props, eventBus, outGW),
"actorMonitor-" + props.meetingProp.intId)
var actorMonitor = context.actorOf(
MeetingActorInternal.props(props, eventBus, outGW),
"actorMonitor-" + props.meetingProp.intId
)
/** Subscribe to meeting and voice events. **/
eventBus.subscribe(actorMonitor, props.meetingProp.intId)
eventBus.subscribe(actorMonitor, props.voiceProp.voiceConf)
eventBus.subscribe(actorMonitor, props.screenshareProps.screenshareConf)
val presentationApp2x = new PresentationApp2x(liveMeeting, outGW)
val screenshareApp2x = new ScreenshareApp2x(liveMeeting, outGW)
val captionApp2x = new CaptionApp2x(liveMeeting, outGW)
val sharedNotesApp2x = new SharedNotesApp2x(liveMeeting, outGW)
val chatApp2x = new ChatApp2x(liveMeeting, outGW)
val usersApp = new UsersApp(liveMeeting, outGW)
val presentationApp2x = new PresentationApp2x(liveMeeting, outGW = outGW)
val screenshareApp2x = new ScreenshareApp2x(liveMeeting, outGW = outGW)
val captionApp2x = new CaptionApp2x(liveMeeting, outGW = outGW)
val sharedNotesApp2x = new SharedNotesApp2x(liveMeeting, outGW = outGW)
val chatApp2x = new ChatApp2x(liveMeeting, outGW = outGW)
//var inactivityTracker = new MeetingInactivityTracker()
/*******************************************************************/
//object FakeTestData extends FakeTestData
@ -105,42 +113,44 @@ class MeetingActor(val props: DefaultProps,
def receive = {
//=============================
// 2x messages
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
// Handling RegisterUserReqMsg as it is forwarded from BBBActor and
// its type is not BbbCommonEnvCoreMsg
case m: RegisterUserReqMsg => handleRegisterUserReqMsg(m)
case m: GetAllMeetingsReqMsg => handleGetAllMeetingsReqMsg(m)
case m: RegisterUserReqMsg => handleRegisterUserReqMsg(m)
case m: GetAllMeetingsReqMsg => handleGetAllMeetingsReqMsg(m)
// Meeting
case m: DestroyMeetingSysCmdMsg => handleDestroyMeetingSysCmdMsg(m)
case m: DestroyMeetingSysCmdMsg => handleDestroyMeetingSysCmdMsg(m)
//======================================
//=======================================
// old messages
case msg: MonitorNumberOfUsers => handleMonitorNumberOfUsers(msg)
case msg: MonitorNumberOfUsers => handleMonitorNumberOfUsers(msg)
case msg: AllowUserToShareDesktop => handleAllowUserToShareDesktop(msg)
case msg: InitializeMeeting => handleInitializeMeeting(msg)
case msg: ExtendMeetingDuration => handleExtendMeetingDuration(msg)
case msg: SendTimeRemainingUpdate => handleSendTimeRemainingUpdate(msg)
case msg: AllowUserToShareDesktop => handleAllowUserToShareDesktop(msg)
case msg: InitializeMeeting => handleInitializeMeeting(msg)
case msg: ExtendMeetingDuration => handleExtendMeetingDuration(msg)
case msg: SendTimeRemainingUpdate => handleSendTimeRemainingUpdate(msg)
// Screenshare
case msg: DeskShareGetDeskShareInfoRequest => handleDeskShareGetDeskShareInfoRequest(msg)
// Guest
case msg: GetGuestPolicy => handleGetGuestPolicy(msg)
case msg: SetGuestPolicy => handleSetGuestPolicy(msg)
case msg: GetGuestPolicy => handleGetGuestPolicy(msg)
case msg: SetGuestPolicy => handleSetGuestPolicy(msg)
case _ => // do nothing
case _ => // do nothing
}
private def handleBbbCommonEnvCoreMsg(msg: BbbCommonEnvCoreMsg): Unit = {
// TODO: Update meeting activity status here
// updateActivityStatus(msg)
msg.core match {
// Users
case m: ValidateAuthTokenReqMsg => handleValidateAuthTokenReqMsg(m)
case m: ValidateAuthTokenReqMsg => usersApp.handleValidateAuthTokenReqMsg(m)
case m: UserJoinMeetingReqMsg => handleUserJoinMeetingReqMsg(m)
case m: UserLeaveReqMsg => handleUserLeaveReqMsg(m)
case m: UserBroadcastCamStartMsg => handleUserBroadcastCamStartMsg(m)
@ -362,8 +372,10 @@ class MeetingActor(val props: DefaultProps,
BbbCommonEnvCoreMsg(envelope, event)
}
val event = buildRecordingStatusChangedEvtMsg(liveMeeting.props.meetingProp.intId,
"system", MeetingStatus2x.isRecording(liveMeeting.status))
val event = buildRecordingStatusChangedEvtMsg(
liveMeeting.props.meetingProp.intId,
"system", MeetingStatus2x.isRecording(liveMeeting.status)
)
outGW.send(event)
}
@ -385,8 +397,10 @@ class MeetingActor(val props: DefaultProps,
BbbCommonEnvCoreMsg(envelope, event)
}
val event = buildRecordingStatusChangedEvtMsg(liveMeeting.props.meetingProp.intId,
"system", MeetingStatus2x.isRecording(liveMeeting.status))
val event = buildRecordingStatusChangedEvtMsg(
liveMeeting.props.meetingProp.intId,
"system", MeetingStatus2x.isRecording(liveMeeting.status)
)
outGW.send(event)
}

View File

@ -20,17 +20,21 @@ import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.{ Deadline, FiniteDuration }
object MeetingActorInternal {
def props(props: DefaultProps,
def props(
props: DefaultProps,
eventBus: IncomingEventBus,
outGW: OutMessageGateway): Props =
outGW: OutMessageGateway
): Props =
Props(classOf[MeetingActorInternal], props, eventBus, outGW)
}
// This actor is an internal audit actor for each meeting actor that
// periodically sends messages to the meeting actor
class MeetingActorInternal(val props: DefaultProps,
val eventBus: IncomingEventBus, val outGW: OutMessageGateway)
extends Actor with ActorLogging with SystemConfiguration {
class MeetingActorInternal(
val props: DefaultProps,
val eventBus: IncomingEventBus, val outGW: OutMessageGateway
)
extends Actor with ActorLogging with SystemConfiguration with AuditHelpers {
object AuditMonitorInternalMsg
@ -47,7 +51,7 @@ class MeetingActorInternal(val props: DefaultProps,
private def getInactivityDeadline(): Int = {
val time = getMetadata(Metadata.INACTIVITY_DEADLINE, props.metadataProp.metadata) match {
case Some(result) => result.asInstanceOf[Int]
case None => inactivityDeadline
case None => inactivityDeadline
}
log.debug("InactivityDeadline: {} seconds", time)
time
@ -56,7 +60,7 @@ class MeetingActorInternal(val props: DefaultProps,
private def getInactivityTimeLeft(): Int = {
val time = getMetadata(Metadata.INACTIVITY_TIMELEFT, props.metadataProp.metadata) match {
case Some(result) => result.asInstanceOf[Int]
case None => inactivityTimeLeft
case None => inactivityTimeLeft
}
log.debug("InactivityTimeLeft: {} seconds", time)
time
@ -78,7 +82,7 @@ class MeetingActorInternal(val props: DefaultProps,
private val InactivityDeadline = FiniteDuration(getInactivityDeadline(), "seconds")
private val InactivityTimeLeft = FiniteDuration(getInactivityTimeLeft(), "seconds")
private var inactivity = InactivityDeadline.fromNow
private var inactivityDeadlineTime = InactivityDeadline.fromNow
private var inactivityWarning: Option[Deadline] = None
private val ExpireMeetingDuration = FiniteDuration(props.durationProps.duration, "minutes")
@ -91,30 +95,17 @@ class MeetingActorInternal(val props: DefaultProps,
context.system.scheduler.schedule(5 seconds, MonitorFrequency, self, AuditMonitorInternalMsg)
// Query to get voice conference users
def buildGetUsersInVoiceConfSysMsg(meetingId: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(GetUsersInVoiceConfSysMsg.NAME, routing)
val body = GetUsersInVoiceConfSysMsgBody(props.voiceProp.voiceConf)
val header = BbbCoreHeaderWithMeetingId(GetUsersInVoiceConfSysMsg.NAME, meetingId)
val event = GetUsersInVoiceConfSysMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
val event = buildGetUsersInVoiceConfSysMsg(props.meetingProp.intId)
outGW.send(event)
getUsersInVoiceConf(props, outGW)
if (props.meetingProp.isBreakout) {
// This is a breakout room. Inform our parent meeting that we have been successfully created.
eventBus.publish(BigBlueButtonEvent(
props.breakoutProps.parentId,
BreakoutRoomCreated(props.breakoutProps.parentId, props.meetingProp.intId)))
sendBreakoutRoomCreatedToParent(props, eventBus)
}
def receive = {
case AuditMonitorInternalMsg => handleMonitor()
case AuditMonitorInternalMsg => handleMonitor()
case msg: UpdateMeetingExpireMonitor => handleUpdateMeetingExpireMonitor(msg)
case msg: Object => handleMessage(msg)
case msg: Object => handleMessage(msg)
}
def handleMonitor() {
@ -146,28 +137,17 @@ class MeetingActorInternal(val props: DefaultProps,
inactivityWarning match {
case Some(iw) =>
if (inactivity.isOverdue() && iw.isOverdue()) {
if (inactivityDeadlineTime.isOverdue() && iw.isOverdue()) {
log.info("Closing meeting {} due to inactivity for {} seconds", props.meetingProp.intId, InactivityDeadline.toSeconds)
updateInactivityMonitors()
pushInactivityDeadline()
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, EndMeeting(props.meetingProp.intId)))
// Or else make sure to send only one warning message
}
case None =>
if (inactivity.isOverdue()) {
if (inactivityDeadlineTime.isOverdue()) {
log.info("Sending inactivity warning to meeting {}", props.meetingProp.intId)
def build(meetingId: String, timeLeftInSec: Long): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
val envelope = BbbCoreEnvelope(MeetingInactivityWarningEvtMsg.NAME, routing)
val body = MeetingInactivityWarningEvtMsgBody(timeLeftInSec)
val header = BbbClientMsgHeader(MeetingInactivityWarningEvtMsg.NAME, meetingId, "not-used")
val event = MeetingInactivityWarningEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
val event = build(props.meetingProp.intId, InactivityTimeLeft.toSeconds)
outGW.send(event)
sendMeetingInactivityWarning(props, outGW, InactivityTimeLeft.toSeconds)
// We add 5 seconds so clients will have enough time to process the message
inactivityWarning = Some((InactivityTimeLeft + (5 seconds)).fromNow)
@ -198,7 +178,6 @@ class MeetingActorInternal(val props: DefaultProps,
eventBus.publish(BigBlueButtonEvent(props.meetingProp.intId, EndMeeting(props.meetingProp.intId)))
}
}
}
private def handleUpdateMeetingExpireMonitor(msg: UpdateMeetingExpireMonitor) {
@ -215,8 +194,8 @@ class MeetingActorInternal(val props: DefaultProps,
}
}
private def updateInactivityMonitors() {
inactivity = InactivityDeadline.fromNow
private def pushInactivityDeadline() {
inactivityDeadlineTime = InactivityDeadline.fromNow
inactivityWarning = None
}
@ -224,38 +203,26 @@ class MeetingActorInternal(val props: DefaultProps,
for {
_ <- inactivityWarning
} yield {
val event = buildMeetingIsActiveEvtMsg(props.meetingProp.intId)
outGW.send(event)
sendMeetingIsActive(props, outGW)
}
updateInactivityMonitors()
}
def buildMeetingIsActiveEvtMsg(meetingId: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
val envelope = BbbCoreEnvelope(MeetingIsActiveEvtMsg.NAME, routing)
val body = MeetingIsActiveEvtMsgBody(meetingId)
val header = BbbClientMsgHeader(MeetingIsActiveEvtMsg.NAME, meetingId, "not-used")
val event = MeetingIsActiveEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
pushInactivityDeadline()
}
private def handleActivityResponse(msg: ActivityResponse) {
log.info("User endorsed that meeting {} is active", props.meetingProp.intId)
updateInactivityMonitors()
val event = buildMeetingIsActiveEvtMsg(props.meetingProp.intId)
outGW.send(event)
pushInactivityDeadline()
sendMeetingIsActive(props, outGW)
}
private def isMeetingActivity(msg: Object): Boolean = {
// We need to avoid all internal system's messages
msg match {
case msg: MonitorNumberOfUsers => false
case msg: MonitorNumberOfUsers => false
case msg: SendTimeRemainingUpdate => false
case msg: SendBreakoutUsersUpdate => false
case msg: BreakoutRoomCreated => false
case _ => true
case msg: BreakoutRoomCreated => false
case _ => true
}
}
@ -272,14 +239,14 @@ class MeetingActorInternal(val props: DefaultProps,
// Can be defined between 1 minute to 6 hours
metadataIntegerValueOf(v, 60, 21600) match {
case Some(r) => Some(r.asInstanceOf[Object])
case None => None
case None => None
}
case Metadata.INACTIVITY_TIMELEFT =>
// Can be defined between 30 seconds to 30 minutes
metadataIntegerValueOf(v, 30, 1800) match {
case Some(r) => Some(r.asInstanceOf[Object])
case None => None
case None => None
}
case _ => None

View File

@ -0,0 +1,71 @@
package org.bigbluebutton.core.running
import java.util.concurrent.TimeUnit
import org.bigbluebutton.core.domain.MeetingInactivityTracker
import com.softwaremill.quicklens._
import org.bigbluebutton.common2.domain.DefaultProps
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.OutMessageGateway
trait MeetingInactivityTrackerHelper {
def shouldSendInactivityWarning(now: Long, tracker: MeetingInactivityTracker): Boolean = {
(!tracker.warningSent) &&
(tracker.lastActivityTime + tracker.maxInactivityTimeoutMinutes) < (now + tracker.warningMinutesBeforeMax)
}
def isMeetingActive(now: Long, tracker: MeetingInactivityTracker): Boolean = {
(now - tracker.lastActivityTime) < tracker.maxInactivityTimeoutMinutes
}
def isMeetingInactive(now: Long, tracker: MeetingInactivityTracker): Boolean = {
(tracker.warningSent) && (now - tracker.lastActivityTime) > tracker.maxInactivityTimeoutMinutes
}
def processMeetingInactivityAudit(tracker: MeetingInactivityTracker): MeetingInactivityTracker = {
val now = System.currentTimeMillis()
if (isMeetingActive(now, tracker)) {
tracker
} else {
if (isMeetingInactive(now, tracker)) {
sendMeetingInactive
endMeeting
} else {
warnOfMeetingInactivity(tracker)
}
}
}
def timeLeftInMinutes(nowInMins: Long, ) : Int = {
}
def nowInMinutes() : Long = {
TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis())
}
def warnOfMeetingInactivity(now: Long, tracker: MeetingInactivityTracker): MeetingInactivityTracker = {
if (tracker.warningSent) {
tracker
} else {
val timeLeftSeconds = tracker.lastActivityTime + tracker.maxInactivityTimeoutMinutes - now
sendMeetingInactivityWarning(props, outGW, timeLeftSeconds)
tracker.modify(_.warningSent).setTo(true).modify(_.warningSentOn).setTo(System.currentTimeMillis())
}
}
def sendMeetingInactivityWarning(props: DefaultProps, outGW: OutMessageGateway, timeLeftSeconds: Long): Unit = {
def build(meetingId: String, timeLeftInSec: Long): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, "not-used")
val envelope = BbbCoreEnvelope(MeetingInactivityWarningEvtMsg.NAME, routing)
val body = MeetingInactivityWarningEvtMsgBody(timeLeftInSec)
val header = BbbClientMsgHeader(MeetingInactivityWarningEvtMsg.NAME, meetingId, "not-used")
val event = MeetingInactivityWarningEvtMsg(header, body)
BbbCommonEnvCoreMsg(envelope, event)
}
val event = build(props.meetingProp.intId, timeLeftSeconds)
outGW.send(event)
}
}

View File

@ -10,12 +10,12 @@ import org.bigbluebutton.core2.MeetingStatus2x
object RunningMeeting {
def apply(props: DefaultProps, outGW: OutMessageGateway,
eventBus: IncomingEventBus)(implicit context: ActorContext) =
eventBus: IncomingEventBus)(implicit context: ActorContext) =
new RunningMeeting(props, outGW, eventBus)(context)
}
class RunningMeeting(val props: DefaultProps, val outGW: OutMessageGateway,
val eventBus: IncomingEventBus)(implicit val context: ActorContext) {
val eventBus: IncomingEventBus)(implicit val context: ActorContext) {
val chatModel = new ChatModel()
val layoutModel = new LayoutModel()

View File

@ -12,7 +12,7 @@ object Model1x2xConverter {
}
def defaultUserVO(intId: String, extId: String, name: String, role: String, guest: Boolean, authed: Boolean,
waitingForAcceptance: Boolean, lockStatus: Boolean, vu: VoiceUserVO): UserVO = {
waitingForAcceptance: Boolean, lockStatus: Boolean, vu: VoiceUserVO): UserVO = {
new UserVO(intId, extId, name, role, guest, authed, waitingForAcceptance = waitingForAcceptance,
emojiStatus = "none", presenter = false,
hasStream = false, locked = lockStatus,

View File

@ -15,7 +15,7 @@ class FromAkkaAppsMsgSenderActor(msgSender: MessageSender)
def receive = {
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
case _ => log.warning("Cannot handle message ")
case _ => log.warning("Cannot handle message ")
}
def handleBbbCommonEnvCoreMsg(msg: BbbCommonEnvCoreMsg): Unit = {
@ -23,8 +23,8 @@ class FromAkkaAppsMsgSenderActor(msgSender: MessageSender)
msg.envelope.name match {
case SyncGetPresentationInfoRespMsg.NAME => msgSender.send(toHTML5RedisChannel, json)
case SyncGetMeetingInfoRespMsg.NAME => msgSender.send(toHTML5RedisChannel, json)
case SyncGetUsersMeetingRespMsg.NAME => msgSender.send(toHTML5RedisChannel, json)
case SyncGetMeetingInfoRespMsg.NAME => msgSender.send(toHTML5RedisChannel, json)
case SyncGetUsersMeetingRespMsg.NAME => msgSender.send(toHTML5RedisChannel, json)
// Sent to FreeSWITCH
case ScreenshareStartRtmpBroadcastVoiceConfMsg.NAME =>

View File

@ -11,13 +11,15 @@ trait ChangeLockSettingsInMeetingCmdMsgHdlr {
val outGW: OutMessageGateway
def handleSetLockSettings(msg: ChangeLockSettingsInMeetingCmdMsg) {
val settings = Permissions(disableCam = msg.body.disableCam,
val settings = Permissions(
disableCam = msg.body.disableCam,
disableMic = msg.body.disableMic,
disablePrivChat = msg.body.disablePrivChat,
disablePubChat = msg.body.disablePubChat,
lockedLayout = msg.body.lockedLayout,
lockOnJoin = msg.body.lockOnJoin,
lockOnJoinConfigurable = msg.body.lockOnJoinConfigurable)
lockOnJoinConfigurable = msg.body.lockOnJoinConfigurable
)
if (!liveMeeting.permissionsEqual(settings)) {
liveMeeting.newPermissions(settings)
@ -25,11 +27,13 @@ trait ChangeLockSettingsInMeetingCmdMsgHdlr {
def build(meetingId: String, userId: String, settings: Permissions, setBy: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.BROADCAST_TO_MEETING, meetingId, userId)
val envelope = BbbCoreEnvelope(LockSettingsInMeetingChangedEvtMsg.NAME, routing)
val body = LockSettingsInMeetingChangedEvtMsgBody(disableCam = settings.disableCam,
val body = LockSettingsInMeetingChangedEvtMsgBody(
disableCam = settings.disableCam,
disableMic = settings.disableMic, disablePrivChat = settings.disablePrivChat,
disablePubChat = settings.disablePubChat, lockedLayout = settings.lockedLayout,
lockOnJoin = settings.lockOnJoin, lockOnJoinConfigurable = settings.lockOnJoinConfigurable,
setBy)
setBy
)
val header = BbbClientMsgHeader(LockSettingsInMeetingChangedEvtMsg.NAME, meetingId, userId)
val event = LockSettingsInMeetingChangedEvtMsg(header, body)

View File

@ -30,7 +30,7 @@ trait MuteAllExceptPresentersCmdMsgHdlr {
if (!vu.listenOnly) {
Users2x.findWithIntId(liveMeeting.users2x, vu.intId) match {
case Some(u) => if (!u.presenter) muteUserInVoiceConf(vu)
case None => muteUserInVoiceConf(vu)
case None => muteUserInVoiceConf(vu)
}
}
}

View File

@ -16,7 +16,7 @@ trait RecordingStartedVoiceConfEvtMsgHdlr {
MeetingStatus2x.setVoiceRecordingFilename(liveMeeting.status, msg.body.stream)
def buildVoiceRecordingStartedEvtMsg(meetingId: String, stream: String, timestamp: String,
voiceConf: String): BbbCommonEnvCoreMsg = {
voiceConf: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(VoiceRecordingStartedEvtMsg.NAME, routing)
@ -34,7 +34,7 @@ trait RecordingStartedVoiceConfEvtMsgHdlr {
MeetingStatus2x.setVoiceRecordingFilename(liveMeeting.status, "")
def buildVoiceRecordingStoppedEvtMsg(meetingId: String, stream: String, timestamp: String,
voiceConf: String): BbbCommonEnvCoreMsg = {
voiceConf: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
val envelope = BbbCoreEnvelope(VoiceRecordingStoppedEvtMsg.NAME, routing)

View File

@ -17,7 +17,8 @@ trait GetGuestsWaitingApprovalReqMsgHdlr extends HandlerHelpers {
val event = MsgBuilder.buildGetGuestsWaitingApprovalRespMsg(
liveMeeting.props.meetingProp.intId,
msg.body.requesterId,
guests)
guests
)
Sender.send(outGW, event)

View File

@ -30,8 +30,10 @@ trait GuestsWaitingApprovedMsgHdlr extends HandlerHelpers {
RegisteredUsers.setWaitingForApproval(liveMeeting.registeredUsers, u, false)
// send message to user that he has been approved
}
val event = MsgBuilder.buildGuestApprovedEvtMsg(liveMeeting.props.meetingProp.intId,
g.intId, guest.approved, approvedBy)
val event = MsgBuilder.buildGuestApprovedEvtMsg(
liveMeeting.props.meetingProp.intId,
g.intId, guest.approved, approvedBy
)
Sender.send(outGW, event)
@ -41,8 +43,10 @@ trait GuestsWaitingApprovedMsgHdlr extends HandlerHelpers {
def notifyModeratorsOfGuestsApproval(guests: Vector[GuestApprovedVO], approvedBy: String): Unit = {
val mods = Users2x.findAll(liveMeeting.users2x).filter(p => p.role == Roles.MODERATOR_ROLE)
mods foreach { m =>
val event = MsgBuilder.buildGuestsWaitingApprovedEvtMsg(liveMeeting.props.meetingProp.intId,
m.intId, guests, approvedBy)
val event = MsgBuilder.buildGuestsWaitingApprovedEvtMsg(
liveMeeting.props.meetingProp.intId,
m.intId, guests, approvedBy
)
Sender.send(outGW, event)
}
}

View File

@ -18,7 +18,8 @@ trait SetGuestPolicyMsgHdlr {
val policy = GuestPolicy(newPolicy, msg.body.setBy)
GuestsWaiting.setGuestPolicy(liveMeeting.guestsWaiting, policy)
val event = MsgBuilder.buildGuestPolicyChangedEvtMsg(
liveMeeting.props.meetingProp.intId, msg.header.userId, newPolicy, msg.body.setBy)
liveMeeting.props.meetingProp.intId, msg.header.userId, newPolicy, msg.body.setBy
)
Sender.send(outGW, event)
}
}

View File

@ -16,8 +16,10 @@ trait DestroyMeetingSysCmdMsgHdlr {
log.info("Handling DestroyMeeting message for meetingId={}", msg.body.meetingId)
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)
log.info(
"Informing parent meeting {} that a breakout room has been ended {}",
liveMeeting.props.breakoutProps.parentId, liveMeeting.props.meetingProp.intId
)
// send out BreakoutRoomEndedEvtMsg to inform clients the breakout has ended
outGW.send(MsgBuilder.buildBreakoutRoomEndedEvtMsg(liveMeeting.props.meetingProp.intId, "not-used",
@ -28,8 +30,10 @@ trait DestroyMeetingSysCmdMsgHdlr {
outGW.send(MsgBuilder.buildEndAndKickAllSysMsg(liveMeeting.props.meetingProp.intId, "not-used"))
// Eject all users from the voice conference
outGW.send(MsgBuilder.buildEjectAllFromVoiceConfMsg(liveMeeting.props.meetingProp.intId,
liveMeeting.props.voiceProp.voiceConf))
outGW.send(MsgBuilder.buildEjectAllFromVoiceConfMsg(
liveMeeting.props.meetingProp.intId,
liveMeeting.props.voiceProp.voiceConf
))
// send a system message to force disconnection
outGW.send(MsgBuilder.buildDisconnectAllClientsSysMsg(liveMeeting.props.meetingProp.intId))

View File

@ -2,11 +2,12 @@ package org.bigbluebutton.core2.message.handlers.users
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.OutMessageGateway
import org.bigbluebutton.core.apps.users.UsersApp
import org.bigbluebutton.core.models._
import org.bigbluebutton.core.running.{ HandlerHelpers, LiveMeeting, BaseMeetingActor }
import org.bigbluebutton.core.running.{ HandlerHelpers, LiveMeeting }
trait ValidateAuthTokenReqMsgHdlr extends HandlerHelpers {
this: BaseMeetingActor =>
this: UsersApp =>
val liveMeeting: LiveMeeting
val outGW: OutMessageGateway
@ -37,33 +38,3 @@ trait ValidateAuthTokenReqMsgHdlr extends HandlerHelpers {
}
}
}
trait FooValidateAuthTokenReqMsgHdlr extends HandlerHelpers {
val liveMeeting: LiveMeeting
val outGW: OutMessageGateway
def handleValidateAuthTokenReqMsg(msg: ValidateAuthTokenReqMsg): Unit = {
RegisteredUsers.getRegisteredUserWithToken(msg.body.authToken, msg.body.userId, liveMeeting.registeredUsers) match {
case Some(u) =>
val guestPolicyType = GuestsWaiting.getGuestPolicy(liveMeeting.guestsWaiting).policy
if (guestPolicyType == GuestPolicyType.ALWAYS_ACCEPT) {
userValidatedAndNoNeedToWaitForApproval(outGW, liveMeeting, u)
} else if (guestPolicyType == GuestPolicyType.ASK_MODERATOR) {
if (u.guest && u.waitingForAcceptance) {
userValidatedButNeedToWaitForApproval(outGW, liveMeeting, u)
} else {
userValidatedAndNoNeedToWaitForApproval(outGW, liveMeeting, u)
}
} else {
validateTokenFailed(outGW, meetingId = liveMeeting.props.meetingProp.intId,
userId = msg.body.userId, authToken = msg.body.authToken, valid = false, waitForApproval = false)
// TODO: Disconnect user
}
case None =>
validateTokenFailed(outGW, meetingId = liveMeeting.props.meetingProp.intId,
userId = msg.body.userId, authToken = msg.body.authToken, valid = false, waitForApproval = false)
// TODO: Disconnect user
}
}
}

View File

@ -28,7 +28,7 @@ object MsgBuilder {
}
def buildGuestsWaitingApprovedEvtMsg(meetingId: String, userId: String,
guests: Vector[GuestApprovedVO], approvedBy: String): BbbCommonEnvCoreMsg = {
guests: Vector[GuestApprovedVO], approvedBy: String): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, meetingId, userId)
val envelope = BbbCoreEnvelope(GuestsWaitingApprovedEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(GuestsWaitingApprovedEvtMsg.NAME, meetingId, userId)
@ -64,7 +64,7 @@ object MsgBuilder {
}
def buildValidateAuthTokenRespMsg(meetingId: String, userId: String, authToken: String,
valid: Boolean, waitForApproval: Boolean): BbbCommonEnvCoreMsg = {
valid: Boolean, waitForApproval: Boolean): BbbCommonEnvCoreMsg = {
val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, meetingId, userId)
val envelope = BbbCoreEnvelope(ValidateAuthTokenRespMsg.NAME, routing)
val header = BbbClientMsgHeader(ValidateAuthTokenRespMsg.NAME, meetingId, userId)

View File

@ -6,7 +6,7 @@ import org.bigbluebutton.core.OutMessageGateway
object ValidateAuthTokenRespMsgSender {
def send(outGW: OutMessageGateway, meetingId: String, userId: String, authToken: String,
valid: Boolean, waitForApproval: Boolean): Unit = {
valid: Boolean, waitForApproval: Boolean): Unit = {
val routing = Routing.addMsgToClientRouting(MessageTypes.DIRECT, meetingId, userId)
val envelope = BbbCoreEnvelope(ValidateAuthTokenRespMsg.NAME, routing)
val header = BbbClientMsgHeader(ValidateAuthTokenRespMsg.NAME, meetingId, userId)

View File

@ -33,7 +33,7 @@ trait FakeTestData {
}
def createUserVoiceAndCam(liveMeeting: LiveMeeting, role: String, guest: Boolean, authed: Boolean, callingWith: String,
muted: Boolean, talking: Boolean, listenOnly: Boolean): Unit = {
muted: Boolean, talking: Boolean, listenOnly: Boolean): Unit = {
val ruser1 = FakeUserGenerator.createFakeRegisteredUser(liveMeeting.registeredUsers, Roles.MODERATOR_ROLE, true, false)

View File

@ -26,8 +26,7 @@ object FakeUserGenerator {
"Jake", "James", "Jason", "Joe", "John", "Jonathan", "Joseph", "Joshua", "Julian", "Justin", "Keith", "Kevin",
"Leonard", "Liam", "Lucas", "Luke", "Matt", "Max", "Michael", "Nathan", "Neil", "Nicholas", "Oliver", "Owen",
"Paul", "Peter", "Phil", "Piers", "Richard", "Robert", "Ryan", "Sam", "Sean", "Sebastian", "Simon", "Stephen",
"Steven", "Stewart", "Thomas", "Tim", "Trevor", "Victor", "Warren", "William"
)
"Steven", "Stewart", "Thomas", "Tim", "Trevor", "Victor", "Warren", "William")
private val lastNames = Seq("Abraham", "Allan", "Alsop", "Anderson", "Arnold", "Avery", "Bailey", "Baker", "Ball", "Bell",
"Berry", "Black", "Blake", "Bond", "Bower", "Brown", "Buckland", "Burgess", "Butler", "Cameron", "Campbell",
@ -42,8 +41,7 @@ object FakeUserGenerator {
"Piper", "Poole", "Powell", "Pullman", "Quinn", "Rampling", "Randall", "Rees", "Reid", "Roberts", "Robertson",
"Ross", "Russell", "Rutherford", "Sanderson", "Scott", "Sharp", "Short", "Simpson", "Skinner", "Slater", "Smith",
"Springer", "Stewart", "Sutherland", "Taylor", "Terry", "Thomson", "Tucker", "Turner", "Underwood", "Vance",
"Vaughan", "Walker", "Wallace", "Walsh", "Watson", "Welch", "White", "Wilkins", "Wilson", "Wright", "Young"
)
"Vaughan", "Walker", "Wallace", "Walsh", "Watson", "Welch", "White", "Wilkins", "Wilson", "Wright", "Young")
private def getRandomElement(list: Seq[String], random: Random): String = list(random.nextInt(list.length))
@ -60,14 +58,14 @@ object FakeUserGenerator {
}
def createFakeVoiceUser(user: RegisteredUser, callingWith: String, muted: Boolean, talking: Boolean,
listenOnly: Boolean): VoiceUserState = {
listenOnly: Boolean): VoiceUserState = {
val voiceUserId = RandomStringGenerator.randomAlphanumericString(8)
VoiceUserState(intId = user.id, voiceUserId = voiceUserId, callingWith, callerName = user.name,
callerNum = user.name, muted, talking, listenOnly)
}
def createFakeVoiceOnlyUser(callingWith: String, muted: Boolean, talking: Boolean,
listenOnly: Boolean): VoiceUserState = {
listenOnly: Boolean): VoiceUserState = {
val voiceUserId = RandomStringGenerator.randomAlphanumericString(8)
val intId = "v_" + RandomStringGenerator.randomAlphanumericString(16)
val name = getRandomElement(firstNames, random) + " " + getRandomElement(lastNames, random)

View File

@ -28,10 +28,12 @@ object AppsRedisSubscriberActor extends SystemConfiguration {
}
class AppsRedisSubscriberActor(msgReceiver: RedisMessageReceiver, jsonMsgBus: IncomingJsonMessageBus, redisHost: String,
redisPort: Int,
channels: Seq[String] = Nil, patterns: Seq[String] = Nil)
extends RedisSubscriberActor(new InetSocketAddress(redisHost, redisPort),
channels, patterns, onConnectStatus = connected => { println(s"connected: $connected") }) with SystemConfiguration {
redisPort: Int,
channels: Seq[String] = Nil, patterns: Seq[String] = Nil)
extends RedisSubscriberActor(
new InetSocketAddress(redisHost, redisPort),
channels, patterns, onConnectStatus = connected => { println(s"connected: $connected") }
) with SystemConfiguration {
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
case e: Exception => {

View File

@ -40,35 +40,35 @@ class RedisRecorderActor(val system: ActorSystem)
def receive = {
//case msg: SendPublicMessageEvent => handleSendPublicMessageEvent(msg)
//case msg: ClearPublicChatHistoryReply => handleClearPublicChatHistoryReply(msg)
case msg: ClearPresentationOutMsg => handleClearPresentationOutMsg(msg)
case msg: RemovePresentationOutMsg => handleRemovePresentationOutMsg(msg)
case msg: ResizeAndMoveSlideOutMsg => handleResizeAndMoveSlideOutMsg(msg)
case msg: GotoSlideOutMsg => handleGotoSlideOutMsg(msg)
case msg: SharePresentationOutMsg => handleSharePresentationOutMsg(msg)
case msg: EndAndKickAll => handleEndAndKickAll(msg)
case msg: PresenterAssigned => handleAssignPresenter(msg)
case msg: UserJoined => handleUserJoined(msg)
case msg: UserLeft => handleUserLeft(msg)
case msg: UserStatusChange => handleUserStatusChange(msg)
case msg: UserVoiceMuted => handleUserVoiceMuted(msg)
case msg: UserVoiceTalking => handleUserVoiceTalking(msg)
case msg: UserJoinedVoice => handleUserJoinedVoice(msg)
case msg: UserLeftVoice => handleUserLeftVoice(msg)
case msg: RecordingStatusChanged => handleRecordingStatusChanged(msg)
case msg: UserChangedEmojiStatus => handleChangedUserEmojiStatus(msg)
case msg: UserSharedWebcam => handleUserSharedWebcam(msg)
case msg: UserUnsharedWebcam => handleUserUnsharedWebcam(msg)
case msg: VoiceRecordingStarted => handleVoiceRecordingStarted(msg)
case msg: VoiceRecordingStopped => handleVoiceRecordingStopped(msg)
case msg: ClearPresentationOutMsg => handleClearPresentationOutMsg(msg)
case msg: RemovePresentationOutMsg => handleRemovePresentationOutMsg(msg)
case msg: ResizeAndMoveSlideOutMsg => handleResizeAndMoveSlideOutMsg(msg)
case msg: GotoSlideOutMsg => handleGotoSlideOutMsg(msg)
case msg: SharePresentationOutMsg => handleSharePresentationOutMsg(msg)
case msg: EndAndKickAll => handleEndAndKickAll(msg)
case msg: PresenterAssigned => handleAssignPresenter(msg)
case msg: UserJoined => handleUserJoined(msg)
case msg: UserLeft => handleUserLeft(msg)
case msg: UserStatusChange => handleUserStatusChange(msg)
case msg: UserVoiceMuted => handleUserVoiceMuted(msg)
case msg: UserVoiceTalking => handleUserVoiceTalking(msg)
case msg: UserJoinedVoice => handleUserJoinedVoice(msg)
case msg: UserLeftVoice => handleUserLeftVoice(msg)
case msg: RecordingStatusChanged => handleRecordingStatusChanged(msg)
case msg: UserChangedEmojiStatus => handleChangedUserEmojiStatus(msg)
case msg: UserSharedWebcam => handleUserSharedWebcam(msg)
case msg: UserUnsharedWebcam => handleUserUnsharedWebcam(msg)
case msg: VoiceRecordingStarted => handleVoiceRecordingStarted(msg)
case msg: VoiceRecordingStopped => handleVoiceRecordingStopped(msg)
// case msg: SendWhiteboardAnnotationEvtMsg => handleSendWhiteboardAnnotationEvent(msg)
// case msg: CursorPositionUpdatedEvent => handleCursorPositionUpdatedEvent(msg)
// case msg: ClearWhiteboardEvent => handleClearWhiteboardEvent(msg)
// case msg: UndoWhiteboardEvent => handleUndoWhiteboardEvent(msg)
// case msg: EditCaptionHistoryReply => handleEditCaptionHistoryReply(msg)
case msg: DeskShareStartRTMPBroadcast => handleDeskShareStartRTMPBroadcast(msg)
case msg: DeskShareStopRTMPBroadcast => handleDeskShareStopRTMPBroadcast(msg)
case msg: DeskShareNotifyViewersRTMP => handleDeskShareNotifyViewersRTMP(msg)
case _ => // do nothing
case msg: DeskShareStopRTMPBroadcast => handleDeskShareStopRTMPBroadcast(msg)
case msg: DeskShareNotifyViewersRTMP => handleDeskShareNotifyViewersRTMP(msg)
case _ => // do nothing
}
/* private def handleSendPublicMessageEvent(msg: SendPublicMessageEvent) {

View File

@ -76,10 +76,31 @@ trait AppsTestFixtures {
// meetingModel.setGuestPolicy(props.usersProp.guestPolicy)
// We extract the meeting handlers into this class so it is
// easy to test.
val liveMeeting = new LiveMeeting(defaultProps, meetingStatux2x, deskshareModel, chatModel, layoutModel, layouts,
registeredUsers, polls2x, pollModel, wbModel, presModel, breakoutRooms, captionModel,
notesModel, webcams, voiceUsers, users2x, guestsWaiting)
def newLiveMeeting(): LiveMeeting = {
val chatModel = new ChatModel()
val layoutModel = new LayoutModel()
val layouts = new Layouts()
val pollModel = new PollModel()
val wbModel = new WhiteboardModel()
val presModel = new PresentationModel()
val breakoutRooms = new BreakoutRooms()
val captionModel = new CaptionModel()
val notesModel = new SharedNotesModel()
val registeredUsers = new RegisteredUsers
val meetingStatux2x = new MeetingStatus2x
val webcams = new Webcams
val voiceUsers = new VoiceUsers
val users2x = new Users2x
val polls2x = new Polls
val guestsWaiting = new GuestsWaiting
val deskshareModel = new ScreenshareModel
// meetingModel.setGuestPolicy(props.usersProp.guestPolicy)
// We extract the meeting handlers into this class so it is
// easy to test.
new LiveMeeting(defaultProps, meetingStatux2x, deskshareModel, chatModel, layoutModel, layouts,
registeredUsers, polls2x, pollModel, wbModel, presModel, breakoutRooms, captionModel,
notesModel, webcams, voiceUsers, users2x, guestsWaiting)
}
}

View File

@ -11,8 +11,10 @@ import org.scalatest.{ Matchers, WordSpecLike }
import scala.concurrent.duration._
class BigBlueButtonActorTestsSpec extends TestKit(ActorSystem("BigBlueButtonActorTestsSpec",
ConfigFactory.parseString(TestKitUsageSpec.config)))
class BigBlueButtonActorTestsSpec extends TestKit(ActorSystem(
"BigBlueButtonActorTestsSpec",
ConfigFactory.parseString(TestKitUsageSpec.config)
))
with DefaultTimeout with ImplicitSender with WordSpecLike
with Matchers with StopSystemAfterAll with AppsTestFixtures with SystemConfiguration {
@ -20,12 +22,12 @@ class BigBlueButtonActorTestsSpec extends TestKit(ActorSystem("BigBlueButtonActo
// Setup dependencies
val bbbMsgBus = new BbbMsgRouterEventBus
val eventBus = new IncomingEventBus
val eventBus = new InMsgBusGW(new IncomingEventBusImp())
val outgoingEventBus = new OutgoingEventBus
val outBus2 = new OutEventBus2
val recordBus = new RecordingEventBus
val outGW = OutMessageGatewayImp(outgoingEventBus, outBus2, recordBus)
//val outGW = OutMessageGatewayImp(outgoingEventBus, outBus2, recordBus)
// Have the build in testActor receive messages coming from class under test (BigBlueButtonActor)
outBus2.subscribe(testActor, outBbbMsgMsgChannel)
@ -34,22 +36,27 @@ class BigBlueButtonActorTestsSpec extends TestKit(ActorSystem("BigBlueButtonActo
"Send a MeetingCreatedEvtMsg when receiving CreateMeetingReqMsg" in {
within(500 millis) {
val outGWSeq = new OutMsgGWSeq()
// Create BigBlueButton Actor
val bbbActorRef = system.actorOf(BigBlueButtonActor.props(system,
eventBus, bbbMsgBus, outGW))
val bbbActorRef = system.actorOf(BigBlueButtonActor.props(
system,
eventBus, bbbMsgBus, outGWSeq
))
// Send our create meeting request message
val msg = buildCreateMeetingReqMsg(defaultProps)
bbbActorRef ! msg
//assert(outGWSeq.msgs.length == 2)
// Expect a message from BigBlueButtonActor as a result of handling
// the create meeting request message.
//expectMsgClass(classOf[BbbCommonEnvCoreMsg])
expectMsgPF() {
case event: BbbCommonEnvCoreMsg =>
assert(event.envelope.name == MeetingCreatedEvtMsg.NAME)
// Can do more assertions here
}
// expectMsgPF() {
// case event: BbbCommonEnvCoreMsg =>
// assert(event.envelope.name == MeetingCreatedEvtMsg.NAME)
// Can do more assertions here
// }
}
}
}

View File

@ -21,7 +21,7 @@ class JsonMessageDecoderTests extends UnitSpec with JsonMessageFixtures {
it should "fail to decode CreateBreakoutRoomsRequestMessage" in {
JsonMessageDecoder.decode(invalidCreateBreakoutRoomsRequestMessage) match {
case Some(validMsg) => fail("Should have failed to decode message")
case None => assert(true)
case None => assert(true)
}
}

View File

@ -0,0 +1,15 @@
package org.bigbluebutton.core
import akka.actor.Props
import org.bigbluebutton.core.running.BaseMeetingActor
object MockTestActor {
def props(): Props = Props(classOf[MockTestActor])
}
class MockTestActor extends BaseMeetingActor {
def receive = {
case _ => log.error("Shouldn't receive anything as this is just an actor stand in.")
}
}

View File

@ -18,8 +18,10 @@ import org.scalatest.Matchers
/**
* a Test to show some TestKit examples
*/
class TestKitUsageSpec extends TestKit(ActorSystem("TestKitUsageSpec",
ConfigFactory.parseString(TestKitUsageSpec.config)))
class TestKitUsageSpec extends TestKit(ActorSystem(
"TestKitUsageSpec",
ConfigFactory.parseString(TestKitUsageSpec.config)
))
with DefaultTimeout with ImplicitSender with WordSpecLike
with Matchers with BeforeAndAfterAll {
@ -130,7 +132,7 @@ object TestKitUsageSpec {
class FilteringActor(next: ActorRef) extends Actor {
def receive = {
case msg: String => next ! msg
case _ => None
case _ => None
}
}
@ -141,7 +143,7 @@ object TestKitUsageSpec {
* be bothered with the rest
*/
class SequencingActor(next: ActorRef, head: immutable.Seq[String],
tail: immutable.Seq[String]) extends Actor {
tail: immutable.Seq[String]) extends Actor {
def receive = {
case msg => {
head foreach { next ! _ }

View File

@ -26,7 +26,7 @@ class DirectChatModelTest extends UnitSpec {
val dc2 = DirectChats.find(between, directChats)
dc2 match {
case Some(directChat) => assert(directChat.messages.length == 2)
case None => fail("No direct chat found!")
case None => fail("No direct chat found!")
}
// Append a third message and make sure there are three messages
@ -37,7 +37,7 @@ class DirectChatModelTest extends UnitSpec {
val dc3 = DirectChats.find(between, directChats)
dc3 match {
case Some(directChat) => assert(directChat.messages.length == 3)
case None => fail("No direct chat found!")
case None => fail("No direct chat found!")
}
}

View File

@ -0,0 +1,33 @@
package org.bigbluebutton.core.running
import org.bigbluebutton.core.UnitSpec
import org.bigbluebutton.core.domain.MeetingInactivityTracker
class MeetingInactivityTrackerHelperTests extends UnitSpec {
"A MeetingInactivityTrackerHelper" should "be return meeting is inactive" in {
object Handler extends MeetingInactivityTrackerHelper
val tracker = new MeetingInactivityTracker(20, 5, 10, false, 0L)
val active = Handler.isMeetingActive(40, tracker)
assert(active == false)
}
"A MeetingInactivityTrackerHelper" should "be return meeting is active" in {
object Handler extends MeetingInactivityTrackerHelper
val tracker = new MeetingInactivityTracker(20, 5, 10, false, 0L)
val active = Handler.isMeetingActive(12, tracker)
assert(active)
}
"A MeetingInactivityTrackerHelper" should "be return send warning if close to max inactivity" in {
object Handler extends MeetingInactivityTrackerHelper
val tracker = new MeetingInactivityTracker(20, 5, 10, false, 0L)
val send = Handler.shouldSendInactivityWarning(now = 28, tracker)
assert(send)
}
}

View File

@ -1,22 +1,24 @@
package org.bigbluebutton.core2.message.handlers
import akka.actor.{ ActorSystem, Props }
import akka.actor.{ ActorContext, ActorSystem, Props }
import akka.testkit.{ DefaultTimeout, ImplicitSender, TestKit }
import com.typesafe.config.ConfigFactory
import org.bigbluebutton.SystemConfiguration
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core._
import org.bigbluebutton.core.apps.users.UsersApp
import org.bigbluebutton.core.bus._
import org.bigbluebutton.core.models._
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting }
import org.bigbluebutton.core2.message.handlers.users.{ FooValidateAuthTokenReqMsgHdlr, ValidateAuthTokenReqMsgHdlr }
import org.bigbluebutton.core.running.LiveMeeting
import org.bigbluebutton.core2.testdata.TestDataGen
import org.scalatest.{ Matchers, WordSpecLike }
import akka.testkit.TestActorRef
import scala.concurrent.duration._
class ValidateAuthTokenReqMsgHdlrTestsSpec extends TestKit(ActorSystem("ValidateAuthTokenReqMsgHdlrTestsSpec",
ConfigFactory.parseString(TestKitUsageSpec.config)))
class ValidateAuthTokenReqMsgHdlrTestsSpec extends TestKit(ActorSystem(
"ValidateAuthTokenReqMsgHdlrTestsSpec",
ConfigFactory.parseString(TestKitUsageSpec.config)
))
with DefaultTimeout with ImplicitSender with WordSpecLike
with Matchers with StopSystemAfterAll with AppsTestFixtures with SystemConfiguration {
@ -26,37 +28,29 @@ class ValidateAuthTokenReqMsgHdlrTestsSpec extends TestKit(ActorSystem("Validate
val outBus2 = new OutEventBus2
val recordBus = new RecordingEventBus
val outGW = OutMessageGatewayImp(outgoingEventBus, outBus2, recordBus)
// Have the build in testActor receive messages coming from class under test
outBus2.subscribe(testActor, outBbbMsgMsgChannel)
"A MeetingActor" should {
"Reject an invalid authToken because there is no registered users in the meeting" in {
within(500 millis) {
// Create actor under test Actor
val meetingActorRef = system.actorOf(ValidateAuthTokenRespMsgTestActor.props(outGW, liveMeeting))
val state = newLiveMeeting()
val outGW = new OutMsgGWSeq()
def build(meetingId: String, userId: String, authToken: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps")
val envelope = BbbCoreEnvelope(CreateMeetingReqMsg.NAME, routing)
val req = ValidateAuthTokenReqMsg(meetingId, userId, authToken)
BbbCommonEnvCoreMsg(envelope, req)
// Need to get an ActorContext
val actorRef = TestActorRef[MockTestActor]
val actor = actorRef.underlyingActor
// Create actor under test Actor
val meetingActorRef = new UsersApp(state, outGW)(actor.context)
def build(meetingId: String, userId: String, authToken: String): ValidateAuthTokenReqMsg = {
ValidateAuthTokenReqMsg(meetingId, userId, authToken)
}
// Send our message
val msg = build(liveMeeting.props.meetingProp.intId, "unknown user", "fake auth token")
meetingActorRef ! msg
val msg = build(state.props.meetingProp.intId, "unknown user", "fake auth token")
meetingActorRef.handleValidateAuthTokenReqMsg(msg)
// Handle message expectations
expectMsgPF() {
case event: BbbCommonEnvCoreMsg =>
assert(event.envelope.name == ValidateAuthTokenRespMsg.NAME)
val outMsg = event.core.asInstanceOf[ValidateAuthTokenRespMsg]
assert(outMsg.body.valid == false)
// Can do more assertions here
}
assert(outGW.msgs.length == 1)
}
}
}
@ -65,31 +59,27 @@ class ValidateAuthTokenReqMsgHdlrTestsSpec extends TestKit(ActorSystem("Validate
"Reject an invalid authToken for a registered users in the meeting" in {
within(500 millis) {
val richard = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Richard", Roles.MODERATOR_ROLE,
val state = newLiveMeeting()
val outGW = new OutMsgGWSeq()
val richard = TestDataGen.createRegisteredUser(state.registeredUsers, "Richard", Roles.MODERATOR_ROLE,
guest = false, authed = false, waitForApproval = false)
// Need to get an ActorContext
val actorRef = TestActorRef[MockTestActor]
val actor = actorRef.underlyingActor
// Create actor under test Actor
val meetingActorRef = system.actorOf(ValidateAuthTokenRespMsgTestActor.props(outGW, liveMeeting))
val meetingActorRef = new UsersApp(state, outGW)(actor.context)
def build(meetingId: String, userId: String, authToken: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps")
val envelope = BbbCoreEnvelope(CreateMeetingReqMsg.NAME, routing)
val req = ValidateAuthTokenReqMsg(meetingId, userId, authToken)
BbbCommonEnvCoreMsg(envelope, req)
def build(meetingId: String, userId: String, authToken: String): ValidateAuthTokenReqMsg = {
ValidateAuthTokenReqMsg(meetingId, userId, authToken)
}
// Send our message
val msg = build(liveMeeting.props.meetingProp.intId, richard.id, "wrong token")
meetingActorRef ! msg
val msg = build(state.props.meetingProp.intId, richard.id, "wrong token")
meetingActorRef.handleValidateAuthTokenReqMsg(msg)
// Handle message expectations
expectMsgPF() {
case event: BbbCommonEnvCoreMsg =>
assert(event.envelope.name == ValidateAuthTokenRespMsg.NAME)
val outMsg = event.core.asInstanceOf[ValidateAuthTokenRespMsg]
assert(outMsg.body.valid == false)
// Can do more assertions here
}
assert(outGW.msgs.length == 1)
}
}
}
@ -97,32 +87,28 @@ class ValidateAuthTokenReqMsgHdlrTestsSpec extends TestKit(ActorSystem("Validate
"A MeetingActor" should {
"Accept a valid authToken for a registered users in the meeting" in {
within(500 millis) {
val state = newLiveMeeting()
val outGW = new OutMsgGWSeq()
val richard = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Richard", Roles.MODERATOR_ROLE,
val richard = TestDataGen.createRegisteredUser(state.registeredUsers, "Richard", Roles.MODERATOR_ROLE,
guest = false, authed = false, waitForApproval = false)
// Need to get an ActorContext
val actorRef = TestActorRef[MockTestActor]
val actor = actorRef.underlyingActor
// Create actor under test Actor
val meetingActorRef = system.actorOf(ValidateAuthTokenRespMsgTestActor.props(outGW, liveMeeting))
val meetingActorRef = new UsersApp(state, outGW)(actor.context)
def build(meetingId: String, userId: String, authToken: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps")
val envelope = BbbCoreEnvelope(CreateMeetingReqMsg.NAME, routing)
val req = ValidateAuthTokenReqMsg(meetingId, userId, authToken)
BbbCommonEnvCoreMsg(envelope, req)
def build(meetingId: String, userId: String, authToken: String): ValidateAuthTokenReqMsg = {
ValidateAuthTokenReqMsg(meetingId, userId, authToken)
}
// Send our message
val msg = build(liveMeeting.props.meetingProp.intId, richard.id, richard.authToken)
meetingActorRef ! msg
val msg = build(state.props.meetingProp.intId, richard.id, richard.authToken)
meetingActorRef.handleValidateAuthTokenReqMsg(msg)
// Handle message expectations
expectMsgPF() {
case event: BbbCommonEnvCoreMsg =>
assert(event.envelope.name == ValidateAuthTokenRespMsg.NAME)
val outMsg = event.core.asInstanceOf[ValidateAuthTokenRespMsg]
assert(outMsg.body.valid == true)
// Can do more assertions here
}
assert(outGW.msgs.length == 6)
}
}
}
@ -130,37 +116,33 @@ class ValidateAuthTokenReqMsgHdlrTestsSpec extends TestKit(ActorSystem("Validate
"A MeetingActor" should {
"Accept a valid authToken for a registered users in the meeting and not wait for approval for none guests" in {
within(500 millis) {
val state = newLiveMeeting()
val outGW = new OutMsgGWSeq()
// Set the guest policy to ask moderator
GuestsWaiting.setGuestPolicy(liveMeeting.guestsWaiting, GuestPolicy(GuestPolicyType.ASK_MODERATOR, "SYSTEM"))
GuestsWaiting.setGuestPolicy(state.guestsWaiting, GuestPolicy(GuestPolicyType.ASK_MODERATOR, "SYSTEM"))
// Register a user that is not a guest
val richard = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Richard", Roles.MODERATOR_ROLE,
val richard = TestDataGen.createRegisteredUser(state.registeredUsers, "Richard", Roles.MODERATOR_ROLE,
guest = false, authed = false, waitForApproval = false)
// Need to get an ActorContext
val actorRef = TestActorRef[MockTestActor]
val actor = actorRef.underlyingActor
// Create actor under test Actor
val meetingActorRef = system.actorOf(ValidateAuthTokenRespMsgTestActor.props(outGW, liveMeeting))
val meetingActorRef = new UsersApp(state, outGW)(actor.context)
def build(meetingId: String, userId: String, authToken: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps")
val envelope = BbbCoreEnvelope(CreateMeetingReqMsg.NAME, routing)
val req = ValidateAuthTokenReqMsg(meetingId, userId, authToken)
BbbCommonEnvCoreMsg(envelope, req)
def build(meetingId: String, userId: String, authToken: String): ValidateAuthTokenReqMsg = {
ValidateAuthTokenReqMsg(meetingId, userId, authToken)
}
// Send our message
val msg = build(liveMeeting.props.meetingProp.intId, richard.id, richard.authToken)
meetingActorRef ! msg
val msg = build(state.props.meetingProp.intId, richard.id, richard.authToken)
meetingActorRef.handleValidateAuthTokenReqMsg(msg)
// Handle message expectations
expectMsgPF() {
case event: BbbCommonEnvCoreMsg =>
assert(event.envelope.name == ValidateAuthTokenRespMsg.NAME)
val outMsg = event.core.asInstanceOf[ValidateAuthTokenRespMsg]
assert(outMsg.body.valid == true)
assert(outMsg.body.waitForApproval == false)
// Can do more assertions here
}
// Handle message expectations
assert(outGW.msgs.length == 6)
}
}
@ -168,108 +150,51 @@ class ValidateAuthTokenReqMsgHdlrTestsSpec extends TestKit(ActorSystem("Validate
"A MeetingActor" should {
"Accept a valid authToken for a registered users in the meeting and wait for approval for guests" in {
within(500 millis) {
// Set the guest policy to ask moderator
GuestsWaiting.setGuestPolicy(liveMeeting.guestsWaiting, GuestPolicy(GuestPolicyType.ASK_MODERATOR, "SYSTEM"))
// Register a user that is not a guest
val richard = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Richard", Roles.MODERATOR_ROLE,
guest = false, authed = false, waitForApproval = false)
val fred = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Fred", Roles.MODERATOR_ROLE,
guest = false, authed = false, waitForApproval = false)
val anton = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Anton", Roles.VIEWER_ROLE,
guest = false, authed = false, waitForApproval = false)
val richardUser = TestDataGen.createUserFor(liveMeeting, richard, presenter = false)
val fredUser = TestDataGen.createUserFor(liveMeeting, fred, presenter = false)
val antonUser = TestDataGen.createUserFor(liveMeeting, anton, presenter = false)
val chad = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Chad", Roles.VIEWER_ROLE,
guest = true, authed = false, waitForApproval = true)
val outGWSeq = new OutMsgGWSeq()
// Create actor under test Actor
val meetingActorRef = system.actorOf(ValidateAuthTokenRespMsgTestActor.props(outGWSeq, liveMeeting))
def build(meetingId: String, userId: String, authToken: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps")
val envelope = BbbCoreEnvelope(ValidateAuthTokenReqMsg.NAME, routing)
val req = ValidateAuthTokenReqMsg(meetingId, userId, authToken)
BbbCommonEnvCoreMsg(envelope, req)
}
println("****** Sending validate msg test")
// Send our message
val msg = build(liveMeeting.props.meetingProp.intId, chad.id, chad.authToken)
meetingActorRef ! msg
/**
* // Handle message expectations
* expectMsgPF() {
* case event: BbbCommonEnvCoreMsg =>
* assert(event.envelope.name == ValidateAuthTokenRespMsg.NAME)
* val outMsg = event.core.asInstanceOf[ValidateAuthTokenRespMsg]
* assert(outMsg.body.valid == true)
* assert(outMsg.body.waitForApproval == false)
* // Can do more assertions here
* }
*/
println("******* Asserting message length ")
assert(outGWSeq.msgs.length == 6)
}
}
}
"A MeetingActor" should {
"Accept a valid authToken for a registered users in the meeting and wait for approval for guests 2" in {
within(500 millis) {
val registeredUsers = new RegisteredUsers
val users2x = new Users2x
val liveMeeting = new LiveMeeting(defaultProps, meetingStatux2x, deskshareModel, chatModel, layoutModel, layouts,
val state = new LiveMeeting(defaultProps, meetingStatux2x, deskshareModel, chatModel, layoutModel, layouts,
registeredUsers, polls2x, pollModel, wbModel, presModel, breakoutRooms, captionModel,
notesModel, webcams, voiceUsers, users2x, guestsWaiting)
// Set the guest policy to ask moderator
GuestsWaiting.setGuestPolicy(liveMeeting.guestsWaiting, GuestPolicy(GuestPolicyType.ASK_MODERATOR, "SYSTEM"))
GuestsWaiting.setGuestPolicy(state.guestsWaiting, GuestPolicy(GuestPolicyType.ASK_MODERATOR, "SYSTEM"))
// Register a user that is not a guest
val richard = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Richard", Roles.MODERATOR_ROLE,
val richard = TestDataGen.createRegisteredUser(state.registeredUsers, "Richard", Roles.MODERATOR_ROLE,
guest = false, authed = false, waitForApproval = false)
val fred = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Fred", Roles.MODERATOR_ROLE,
val fred = TestDataGen.createRegisteredUser(state.registeredUsers, "Fred", Roles.MODERATOR_ROLE,
guest = false, authed = false, waitForApproval = false)
val anton = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Anton", Roles.VIEWER_ROLE,
val anton = TestDataGen.createRegisteredUser(state.registeredUsers, "Anton", Roles.VIEWER_ROLE,
guest = false, authed = false, waitForApproval = false)
val richardUser = TestDataGen.createUserFor(liveMeeting, richard, presenter = false)
val fredUser = TestDataGen.createUserFor(liveMeeting, fred, presenter = false)
val antonUser = TestDataGen.createUserFor(liveMeeting, anton, presenter = false)
val richardUser = TestDataGen.createUserFor(state, richard, presenter = false)
val fredUser = TestDataGen.createUserFor(state, fred, presenter = false)
val antonUser = TestDataGen.createUserFor(state, anton, presenter = false)
val chad = TestDataGen.createRegisteredUser(liveMeeting.registeredUsers, "Chad", Roles.VIEWER_ROLE,
val chad = TestDataGen.createRegisteredUser(state.registeredUsers, "Chad", Roles.VIEWER_ROLE,
guest = true, authed = false, waitForApproval = true)
val outGWSeq = new OutMsgGWSeq()
val outGW = new OutMsgGWSeq()
// Need to get an ActorContext
val actorRef = TestActorRef[MockTestActor]
val actor = actorRef.underlyingActor
// Create actor under test Actor
val meetingActorRef = new FooMeeting(outGWSeq, liveMeeting)
val meetingActorRef = new UsersApp(state, outGW)(actor.context)
def build(meetingId: String, userId: String, authToken: String): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-apps")
val envelope = BbbCoreEnvelope(ValidateAuthTokenReqMsg.NAME, routing)
val req = ValidateAuthTokenReqMsg(meetingId, userId, authToken)
BbbCommonEnvCoreMsg(envelope, req)
def build(meetingId: String, userId: String, authToken: String): ValidateAuthTokenReqMsg = {
ValidateAuthTokenReqMsg(meetingId, userId, authToken)
}
println("****** Sending validate msg test")
val msg = build(liveMeeting.props.meetingProp.intId, chad.id, chad.authToken)
meetingActorRef.handleValidateAuthTokenReqMsg(msg.core.asInstanceOf[ValidateAuthTokenReqMsg])
val msg = build(state.props.meetingProp.intId, chad.id, chad.authToken)
meetingActorRef.handleValidateAuthTokenReqMsg(msg)
println("******* Asserting message length ")
assert(outGWSeq.msgs.length == 6)
assert(outGW.msgs.length == 3)
}
}
@ -290,27 +215,3 @@ class ValidateAuthTokenReqMsgHdlrTestsSpec extends TestKit(ActorSystem("Validate
}
}
class FooMeeting(val outGW: OutMessageGateway,
val liveMeeting: LiveMeeting) extends FooValidateAuthTokenReqMsgHdlr {
}
class ValidateAuthTokenRespMsgTestActor(val outGW: OutMessageGateway,
val liveMeeting: LiveMeeting)
extends BaseMeetingActor with ValidateAuthTokenReqMsgHdlr {
def receive = {
case msg: BbbCommonEnvCoreMsg => handleBbbCommonEnvCoreMsg(msg)
}
private def handleBbbCommonEnvCoreMsg(msg: BbbCommonEnvCoreMsg): Unit = {
msg.core match {
case m: ValidateAuthTokenReqMsg => handleValidateAuthTokenReqMsg(m)
}
}
}
object ValidateAuthTokenRespMsgTestActor {
def props(outGW: OutMessageGateway, liveMeeting: LiveMeeting): Props =
Props(classOf[ValidateAuthTokenRespMsgTestActor], outGW, liveMeeting)
}

View File

@ -6,7 +6,7 @@ import org.bigbluebutton.core.util.RandomStringGenerator
object TestDataGen {
def createRegisteredUser(users: RegisteredUsers, name: String, role: String,
guest: Boolean, authed: Boolean, waitForApproval: Boolean): RegisteredUser = {
guest: Boolean, authed: Boolean, waitForApproval: Boolean): RegisteredUser = {
val id = "w_" + RandomStringGenerator.randomAlphanumericString(16)
val extId = RandomStringGenerator.randomAlphanumericString(16)
val authToken = RandomStringGenerator.randomAlphanumericString(16)
@ -18,14 +18,14 @@ object TestDataGen {
}
def createVoiceUserForUser(user: RegisteredUser, callingWith: String, muted: Boolean, talking: Boolean,
listenOnly: Boolean): VoiceUserState = {
listenOnly: Boolean): VoiceUserState = {
val voiceUserId = RandomStringGenerator.randomAlphanumericString(8)
VoiceUserState(intId = user.id, voiceUserId = voiceUserId, callingWith, callerName = user.name,
callerNum = user.name, muted, talking, listenOnly)
}
def createFakeVoiceOnlyUser(callingWith: String, muted: Boolean, talking: Boolean,
listenOnly: Boolean, name: String): VoiceUserState = {
listenOnly: Boolean, name: String): VoiceUserState = {
val voiceUserId = RandomStringGenerator.randomAlphanumericString(8)
val intId = "v_" + RandomStringGenerator.randomAlphanumericString(16)
VoiceUserState(intId, voiceUserId = voiceUserId, callingWith, callerName = name,