diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserJoinMeetingAfterReconnectReqMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserJoinMeetingAfterReconnectReqMsgHdlr.scala
new file mode 100644
index 0000000000..43015c26f5
--- /dev/null
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserJoinMeetingAfterReconnectReqMsgHdlr.scala
@@ -0,0 +1,34 @@
+package org.bigbluebutton.core.apps.users
+
+import org.bigbluebutton.common2.msgs.UserJoinMeetingAfterReconnectReqMsg
+import org.bigbluebutton.core.apps.breakout.BreakoutHdlrHelpers
+import org.bigbluebutton.core.apps.voice.UserJoinedVoiceConfEvtMsgHdlr
+import org.bigbluebutton.core.domain.MeetingState2x
+import org.bigbluebutton.core.models.VoiceUsers
+import org.bigbluebutton.core.running.{ BaseMeetingActor, HandlerHelpers, LiveMeeting, OutMsgRouter }
+
+trait UserJoinMeetingAfterReconnectReqMsgHdlr extends HandlerHelpers with BreakoutHdlrHelpers with UserJoinedVoiceConfEvtMsgHdlr {
+ this: BaseMeetingActor =>
+
+ val liveMeeting: LiveMeeting
+ val outGW: OutMsgRouter
+
+ def handleUserJoinMeetingAfterReconnectReqMsg(msg: UserJoinMeetingAfterReconnectReqMsg, state: MeetingState2x): MeetingState2x = {
+ val newState = userJoinMeeting(outGW, msg.body.authToken, liveMeeting, state)
+
+ if (liveMeeting.props.meetingProp.isBreakout) {
+ updateParentMeetingWithUsers()
+ }
+
+ // recover voice user
+ for {
+ vu <- VoiceUsers.recoverVoiceUser(liveMeeting.voiceUsers, msg.body.userId)
+ } yield {
+ handleUserJoinedVoiceConfEvtMsg(liveMeeting.props.voiceProp.voiceConf, vu.intId, vu.voiceUserId, vu.callingWith, vu.callerName, vu.callerNum, vu.muted, vu.talking)
+ }
+
+ newState
+ }
+
+}
+
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserJoinMeetingReqMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserJoinMeetingReqMsgHdlr.scala
index 28854e5a74..f2b451b3dc 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserJoinMeetingReqMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserJoinMeetingReqMsgHdlr.scala
@@ -2,6 +2,7 @@ package org.bigbluebutton.core.apps.users
import org.bigbluebutton.common2.msgs.UserJoinMeetingReqMsg
import org.bigbluebutton.core.apps.breakout.BreakoutHdlrHelpers
+import org.bigbluebutton.core.models.VoiceUsers
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.running.{ BaseMeetingActor, HandlerHelpers, LiveMeeting, OutMsgRouter }
@@ -18,6 +19,9 @@ trait UserJoinMeetingReqMsgHdlr extends HandlerHelpers with BreakoutHdlrHelpers
updateParentMeetingWithUsers()
}
+ // fresh user joined (not due to reconnection). Clear (pop) the cached voice user
+ VoiceUsers.recoverVoiceUser(liveMeeting.voiceUsers, msg.body.userId)
+
newState
}
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserLeaveReqMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserLeaveReqMsgHdlr.scala
index e279757261..cfe141e650 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserLeaveReqMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/users/UserLeaveReqMsgHdlr.scala
@@ -45,7 +45,7 @@ trait UserLeaveReqMsgHdlr {
val envelope = BbbCoreEnvelope(UserLeftVoiceConfToClientEvtMsg.NAME, routing)
val header = BbbClientMsgHeader(UserLeftVoiceConfToClientEvtMsg.NAME, liveMeeting.props.meetingProp.intId, vu.intId)
- val body = UserLeftVoiceConfToClientEvtMsgBody(voiceConf = liveMeeting.props.voiceProp.voiceConf, intId = vu.intId, voiceUserId = vu.intId)
+ val body = UserLeftVoiceConfToClientEvtMsgBody(voiceConf = liveMeeting.props.voiceProp.voiceConf, intId = vu.intId, voiceUserId = vu.voiceUserId)
val event = UserLeftVoiceConfToClientEvtMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala
index 7a67af294e..a3bdede2ad 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala
@@ -2,7 +2,7 @@ package org.bigbluebutton.core.apps.voice
import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.apps.breakout.BreakoutHdlrHelpers
-import org.bigbluebutton.core.models.{ VoiceUser2x, VoiceUserState, VoiceUsers }
+import org.bigbluebutton.core.models.{ VoiceUserState, VoiceUsers }
import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter }
import org.bigbluebutton.core2.MeetingStatus2x
@@ -15,6 +15,12 @@ trait UserJoinedVoiceConfEvtMsgHdlr extends BreakoutHdlrHelpers {
def handleUserJoinedVoiceConfEvtMsg(msg: UserJoinedVoiceConfEvtMsg): Unit = {
log.info("Received user joined voice conference " + msg)
+ handleUserJoinedVoiceConfEvtMsg(msg.body.voiceConf, msg.body.intId, msg.body.voiceUserId,
+ msg.body.callingWith, msg.body.callerIdName, msg.body.callerIdNum, msg.body.muted, msg.body.talking)
+ }
+
+ def handleUserJoinedVoiceConfEvtMsg(voiceConf: String, intId: String, voiceUserId: String, callingWith: String,
+ callerIdName: String, callerIdNum: String, muted: Boolean, talking: Boolean): Unit = {
def broadcastEvent(voiceUserState: VoiceUserState): Unit = {
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
@@ -26,20 +32,16 @@ trait UserJoinedVoiceConfEvtMsgHdlr extends BreakoutHdlrHelpers {
liveMeeting.props.meetingProp.intId, voiceUserState.intId
)
- val body = UserJoinedVoiceConfToClientEvtMsgBody(voiceConf = msg.body.voiceConf, intId = voiceUserState.intId, voiceUserId = voiceUserState.voiceUserId,
- callerName = voiceUserState.callerName, callerNum = voiceUserState.callerNum, muted = voiceUserState.muted,
- talking = voiceUserState.talking, callingWith = voiceUserState.callingWith, listenOnly = voiceUserState.listenOnly)
+ val body = UserJoinedVoiceConfToClientEvtMsgBody(voiceConf, voiceUserState.intId, voiceUserState.voiceUserId,
+ voiceUserState.callerName, voiceUserState.callerNum, voiceUserState.muted, voiceUserState.talking,
+ voiceUserState.callingWith, voiceUserState.listenOnly)
val event = UserJoinedVoiceConfToClientEvtMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
outGW.send(msgEvent)
-
}
- val voiceUser = VoiceUser2x(msg.body.intId, msg.body.voiceUserId)
- val voiceUserState = VoiceUserState(intId = msg.body.intId, voiceUserId = msg.body.voiceUserId,
- callingWith = msg.body.callingWith, callerName = msg.body.callerIdName, callerNum = msg.body.callerIdNum,
- muted = msg.body.muted, talking = msg.body.talking, listenOnly = false)
+ val voiceUserState = VoiceUserState(intId, voiceUserId, callingWith, callerIdName, callerIdNum, muted, talking, listenOnly = false)
VoiceUsers.add(liveMeeting.voiceUsers, voiceUserState)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/VoiceUsers.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/VoiceUsers.scala
index 53b3988cf1..282999b16d 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/VoiceUsers.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/VoiceUsers.scala
@@ -25,6 +25,10 @@ object VoiceUsers {
users.toVector.find(u => u.intId == intId)
}
+ def recoverVoiceUser(users: VoiceUsers, intId: String): Option[VoiceUserState] = {
+ users.removeFromCache(intId)
+ }
+
def userMuted(users: VoiceUsers, voiceUserId: String, muted: Boolean): Option[VoiceUserState] = {
for {
u <- findWithVoiceUserId(users, voiceUserId)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
index 4cf29839ba..6f0872b82d 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
@@ -62,6 +62,8 @@ class ReceivedJsonMsgHandlerActor(
route[RegisterUserReqMsg](meetingManagerChannel, envelope, jsonNode)
case UserJoinMeetingReqMsg.NAME =>
routeGenericMsg[UserJoinMeetingReqMsg](envelope, jsonNode)
+ case UserJoinMeetingAfterReconnectReqMsg.NAME =>
+ routeGenericMsg[UserJoinMeetingAfterReconnectReqMsg](envelope, jsonNode)
case GetAllMeetingsReqMsg.NAME =>
route[GetAllMeetingsReqMsg](meetingManagerChannel, envelope, jsonNode)
case DestroyMeetingSysCmdMsg.NAME =>
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
index 260fd4c0a5..965d16d973 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
@@ -64,6 +64,7 @@ class MeetingActor(
with PermisssionCheck
with UserBroadcastCamStartMsgHdlr
with UserJoinMeetingReqMsgHdlr
+ with UserJoinMeetingAfterReconnectReqMsgHdlr
with UserBroadcastCamStopMsgHdlr
with UserConnectedToGlobalAudioMsgHdlr
with UserDisconnectedFromGlobalAudioMsgHdlr
@@ -181,6 +182,8 @@ class MeetingActor(
state = usersApp.handleValidateAuthTokenReqMsg(m, state)
case m: UserJoinMeetingReqMsg =>
state = handleUserJoinMeetingReqMsg(m, state)
+ case m: UserJoinMeetingAfterReconnectReqMsg =>
+ state = handleUserJoinMeetingAfterReconnectReqMsg(m, state)
case m: UserLeaveReqMsg =>
state = handleUserLeaveReqMsg(m, state)
case m: UserBroadcastCamStartMsg => handleUserBroadcastCamStartMsg(m)
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala
index aa5bc35f31..ca9d422502 100755
--- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala
@@ -229,6 +229,14 @@ object UserJoinMeetingReqMsg { val NAME = "UserJoinMeetingReqMsg" }
case class UserJoinMeetingReqMsg(header: BbbClientMsgHeader, body: UserJoinMeetingReqMsgBody) extends StandardMsg
case class UserJoinMeetingReqMsgBody(userId: String, authToken: String)
+/**
+ * Sent from Flash client to rejoin meeting after reconnection
+ */
+object UserJoinMeetingAfterReconnectReqMsg { val NAME = "UserJoinMeetingAfterReconnectReqMsg" }
+case class UserJoinMeetingAfterReconnectReqMsg(header: BbbClientMsgHeader, body: UserJoinMeetingAfterReconnectReqMsgBody) extends StandardMsg
+case class UserJoinMeetingAfterReconnectReqMsgBody(userId: String, authToken: String)
+
+
object UserLeaveReqMsg { val NAME = "UserLeaveReqMsg" }
case class UserLeaveReqMsg(header: BbbClientMsgHeader, body: UserLeaveReqMsgBody) extends StandardMsg
case class UserLeaveReqMsgBody(userId: String, sessionId: String)
diff --git a/bigbluebutton-client/src/org/bigbluebutton/core/events/TokenValidReconnectEvent.as b/bigbluebutton-client/src/org/bigbluebutton/core/events/TokenValidReconnectEvent.as
new file mode 100644
index 0000000000..3ff05da640
--- /dev/null
+++ b/bigbluebutton-client/src/org/bigbluebutton/core/events/TokenValidReconnectEvent.as
@@ -0,0 +1,16 @@
+package org.bigbluebutton.core.events
+{
+import flash.events.Event;
+
+public class TokenValidReconnectEvent extends Event
+{
+ public static const TOKEN_VALID_RECONNECT_EVENT:String = "auth token valid reconnect event";
+
+ public function TokenValidReconnectEvent()
+ {
+ super(TOKEN_VALID_RECONNECT_EVENT, true, false);
+ }
+
+}
+
+}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/NetConnectionDelegate.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/NetConnectionDelegate.as
index cd896f1092..9653f1c9cc 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/NetConnectionDelegate.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/NetConnectionDelegate.as
@@ -38,6 +38,7 @@ package org.bigbluebutton.main.model.users
import org.bigbluebutton.core.connection.messages.ValidateAuthTokenReqMsg;
import org.bigbluebutton.core.connection.messages.ValidateAuthTokenReqMsgBody;
import org.bigbluebutton.core.events.TokenValidEvent;
+ import org.bigbluebutton.core.events.TokenValidReconnectEvent;
import org.bigbluebutton.core.managers.ReconnectionManager;
import org.bigbluebutton.core.model.LiveMeeting;
import org.bigbluebutton.core.services.BandwidthMonitor;
@@ -136,15 +137,19 @@ package org.bigbluebutton.main.model.users
LOGGER.info(JSON.stringify(logData));
if (tokenValid) {
- LiveMeeting.inst().me.authTokenValid = true;
- if (waitForApproval) {
- var waitCommand:BBBEvent = new BBBEvent(BBBEvent.WAITING_FOR_MODERATOR_ACCEPTANCE);
- dispatcher.dispatchEvent(waitCommand);
+ LiveMeeting.inst().me.authTokenValid = true;
+ if (waitForApproval) {
+ var waitCommand:BBBEvent = new BBBEvent(BBBEvent.WAITING_FOR_MODERATOR_ACCEPTANCE);
+ dispatcher.dispatchEvent(waitCommand);
+ } else {
+ LiveMeeting.inst().me.waitingForApproval = false;
+ if (reconnecting) {
+ dispatcher.dispatchEvent(new TokenValidReconnectEvent());
} else {
- LiveMeeting.inst().me.waitingForApproval = false;
dispatcher.dispatchEvent(new TokenValidEvent());
- sendConnectionSuccessEvent(userId);
}
+ sendConnectionSuccessEvent(userId);
+ }
} else {
dispatcher.dispatchEvent(new InvalidAuthTokenEvent());
}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as
index 6fd2407513..246944c813 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/main/model/users/UserService.as
@@ -29,6 +29,7 @@ package org.bigbluebutton.main.model.users
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.core.events.LockControlEvent;
import org.bigbluebutton.core.events.TokenValidEvent;
+ import org.bigbluebutton.core.events.TokenValidReconnectEvent;
import org.bigbluebutton.core.events.VoiceConfEvent;
import org.bigbluebutton.core.managers.ConnectionManager;
import org.bigbluebutton.core.model.LiveMeeting;
@@ -149,7 +150,11 @@ package org.bigbluebutton.main.model.users
public function tokenValidEventHandler(event: TokenValidEvent): void {
sender.joinMeeting();
}
-
+
+ public function tokenValidReconnectEventHandler(event: TokenValidReconnectEvent): void {
+ sender.joinMeetingAfterReconnect();
+ }
+
public function logoutEndMeeting():void{
if (this.isModerator()) {
var myUserId: String = UsersUtil.getMyUserID();
@@ -188,6 +193,7 @@ package org.bigbluebutton.main.model.users
reconnecting = false;
} else {
onAllowedToJoin();
+
}
}
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/maps/UsersMainEventMap.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/users/maps/UsersMainEventMap.mxml
index 2a67382431..610e50e8a3 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/maps/UsersMainEventMap.mxml
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/maps/UsersMainEventMap.mxml
@@ -27,6 +27,7 @@ with BigBlueButton; if not, see .
import org.bigbluebutton.core.events.LockControlEvent;
import org.bigbluebutton.core.events.TokenValidEvent;
+ import org.bigbluebutton.core.events.TokenValidReconnectEvent;
import org.bigbluebutton.core.events.VoiceConfEvent;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.events.BreakoutRoomEvent;
@@ -115,7 +116,11 @@ with BigBlueButton; if not, see .
-
+
+
+
+
+
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageSender.as b/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageSender.as
index 28862d9573..5a2201f480 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageSender.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageSender.as
@@ -73,11 +73,29 @@ package org.bigbluebutton.modules.users.services
}, function(status:String):void { // status - On error occurred
var logData:Object = UsersUtil.initLogData();
logData.tags = ["apps"];
- logData.message = "Error occurred assigning a presenter.";
+ logData.message = "Error occurred when user joining.";
LOGGER.info(JSON.stringify(logData));
}, JSON.stringify(message));
}
-
+
+ public function joinMeetingAfterReconnect(): void {
+ LOGGER.info("Sending JOIN MEETING AFTER RECONNECT message");
+
+ var message:Object = {
+ header: {name: "UserJoinMeetingAfterReconnectReqMsg", meetingId: UsersUtil.getInternalMeetingID(), userId: UsersUtil.getMyUserID()},
+ body: {userId: UsersUtil.getMyUserID(), authToken: LiveMeeting.inst().me.authToken}
+ };
+
+ var _nc:ConnectionManager = BBB.initConnectionManager();
+ _nc.sendMessage2x(function(result:String):void { // On successful result
+ }, function(status:String):void { // status - On error occurred
+ var logData:Object = UsersUtil.initLogData();
+ logData.tags = ["apps"];
+ logData.message = "Error occurred when user joining after reconnect.";
+ LOGGER.info(JSON.stringify(logData));
+ }, JSON.stringify(message));
+ }
+
public function assignPresenter(newPresenterUserId:String, newPresenterName:String, assignedBy:String):void {
var message:Object = {
header: {name: "AssignPresenterReqMsg", meetingId: UsersUtil.getInternalMeetingID(), userId: UsersUtil.getMyUserID()},