From 96d30fc9c13dc9656083fca6d2eee7def673c891 Mon Sep 17 00:00:00 2001 From: Pedro Beschorner Marin Date: Tue, 12 Jan 2016 18:40:34 +0000 Subject: [PATCH 1/4] Fixed main reconnection --- .../red5/BigBlueButtonApplication.java | 1 + .../messaging/ConnectionInvokerService.java | 28 +++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/BigBlueButtonApplication.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/BigBlueButtonApplication.java index 0a3e699e19..ada2122d5d 100755 --- a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/BigBlueButtonApplication.java +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/BigBlueButtonApplication.java @@ -133,6 +133,7 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter { connection.setAttribute(Constants.SESSION, bbbSession); connection.setAttribute("INTERNAL_USER_ID", internalUserID); connection.setAttribute("USER_SESSION_ID", sessionId); + connection.setAttribute("TIMESTAMP", System.currentTimeMillis()); red5InGW.initLockSettings(room, lsMap); diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/messaging/ConnectionInvokerService.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/messaging/ConnectionInvokerService.java index fcd5d386d9..271d9d9635 100755 --- a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/messaging/ConnectionInvokerService.java +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/messaging/ConnectionInvokerService.java @@ -21,6 +21,7 @@ package org.bigbluebutton.red5.client.messaging; import java.util.Set; import java.util.ArrayList; import java.util.List; +import java.util.HashSet; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -274,15 +275,32 @@ public class ConnectionInvokerService { } private IConnection getConnection(IScope scope, String userID) { - Set conns = scope.getClientConnections(); - for (IConnection conn : conns) { + Set conns = new HashSet(); + System.out.println(scope.getClientConnections().size()); + for (IConnection conn : scope.getClientConnections()) { String connID = (String) conn.getAttribute("USER_SESSION_ID"); if (connID != null && connID.equals(userID)) { - return conn; + conns.add(conn); } } - log.warn("Failed to get connection for userId = " + userID); - return null; + if (!conns.isEmpty()) { + return getLastConnection(conns); + } else { + log.warn("Failed to get connection for userId = " + userID); + return null; + } + } + + private IConnection getLastConnection(Set conns) { + IConnection conn = null; + for (IConnection c : conns) { + if (conn == null) { + conn = c; + } else if ((long) conn.getAttribute("TIMESTAMP") < (long) c.getAttribute("TIMESTAMP")) { + conn = c; + } + } + return conn; } public IScope getScope(String meetingID) { From 28bf1c9084ab6198860f7a6bc751e11d15a17d0d Mon Sep 17 00:00:00 2001 From: Pedro Beschorner Marin Date: Wed, 13 Jan 2016 13:50:38 +0000 Subject: [PATCH 2/4] Fixed global audio reconnection --- .../bigbluebutton/core/apps/UsersApp.scala | 34 ++++++++++-------- .../bigbluebutton/core/apps/UsersModel.scala | 36 +++++++++++++++++++ .../phone/managers/ConnectionManager.as | 2 +- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala index bff33f23de..95ff877f78 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala @@ -26,11 +26,13 @@ trait UsersApp { val user = usersModel.getUser(msg.userid) user foreach { u => - val vu = u.voiceUser.copy(joined = false, talking = false) - val uvo = u.copy(listenOnly = true, voiceUser = vu) - usersModel.addUser(uvo) - log.info("UserConnectedToGlobalAudio: meetingId=" + mProps.meetingID + " userId=" + uvo.userID + " user=" + uvo) - outGW.send(new UserListeningOnly(mProps.meetingID, mProps.recorded, uvo.userID, uvo.listenOnly)) + if (usersModel.addVoiceConnection(msg.userid)) { + val vu = u.voiceUser.copy(joined = false, talking = false) + val uvo = u.copy(listenOnly = true, voiceUser = vu) + usersModel.addUser(uvo) + log.info("UserConnectedToGlobalAudio: meetingId=" + mProps.meetingID + " userId=" + uvo.userID + " user=" + uvo) + outGW.send(new UserListeningOnly(mProps.meetingID, mProps.recorded, uvo.userID, uvo.listenOnly)) + } } } @@ -39,16 +41,18 @@ trait UsersApp { val user = usersModel.getUser(msg.userid) user foreach { u => - if (!u.joinedWeb) { - val userLeaving = usersModel.removeUser(u.userID) - log.info("Not web user. Send user left message. meetingId=" + mProps.meetingID + " userId=" + u.userID + " user=" + u) - userLeaving foreach (u => outGW.send(new UserLeft(mProps.meetingID, mProps.recorded, u))) - } else { - val vu = u.voiceUser.copy(joined = false) - val uvo = u.copy(listenOnly = false, voiceUser = vu) - usersModel.addUser(uvo) - log.info("UserDisconnectedToGlobalAudio: meetingId=" + mProps.meetingID + " userId=" + uvo.userID + " user=" + uvo) - outGW.send(new UserListeningOnly(mProps.meetingID, mProps.recorded, uvo.userID, uvo.listenOnly)) + if (usersModel.removeVoiceConnection(msg.userid)) { + if (!u.joinedWeb) { + val userLeaving = usersModel.removeUser(u.userID) + log.info("Not web user. Send user left message. meetingId=" + mProps.meetingID + " userId=" + u.userID + " user=" + u) + userLeaving foreach (u => outGW.send(new UserLeft(mProps.meetingID, mProps.recorded, u))) + } else { + val vu = u.voiceUser.copy(joined = false) + val uvo = u.copy(listenOnly = false, voiceUser = vu) + usersModel.addUser(uvo) + log.info("UserDisconnectedToGlobalAudio: meetingId=" + mProps.meetingID + " userId=" + uvo.userID + " user=" + uvo) + outGW.send(new UserListeningOnly(mProps.meetingID, mProps.recorded, uvo.userID, uvo.listenOnly)) + } } } } diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersModel.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersModel.scala index 9fe3bdd34d..1643e1e45b 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersModel.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersModel.scala @@ -14,6 +14,12 @@ class UsersModel { private var regUsers = new collection.immutable.HashMap[String, RegisteredUser] + /* When reconnecting SIP audio, users may receive the connection message + * before the disconnection message. + * This variable is a connection counter that should control this scenario. + */ + private var voiceConnectionCounter = new collection.immutable.HashMap[String, Integer] + private var locked = false private var meetingMuted = false @@ -144,4 +150,34 @@ class UsersModel { case None => } } + + def addVoiceConnection(userID: String): Boolean = { + voiceConnectionCounter.get(userID) match { + case Some(vc) => { + voiceConnectionCounter += userID -> (vc + 1) + false + } + case None => { + voiceConnectionCounter += userID -> 1 + true + } + } + } + + def removeVoiceConnection(userID: String): Boolean = { + voiceConnectionCounter.get(userID) match { + case Some(vc) => { + if (vc == 1) { + voiceConnectionCounter -= userID + true + } else { + voiceConnectionCounter += userID -> (vc - 1) + false + } + } + case None => { + false + } + } + } } \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/ConnectionManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/ConnectionManager.as index e7d03d7437..c276a5f88f 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/ConnectionManager.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/ConnectionManager.as @@ -134,7 +134,7 @@ package org.bigbluebutton.modules.phone.managers { disconnectedEvent.payload.callbackParameters = []; dispatcher.dispatchEvent(disconnectedEvent); - dispatcher.dispatchEvent(new FlashVoiceConnectionStatusEvent(FlashVoiceConnectionStatusEvent.DISCONNECTED)); + dispatcher.dispatchEvent(new FlashVoiceConnectionStatusEvent(FlashVoiceConnectionStatusEvent.DISCONNECTED, reconnecting)); } } From afb1cc44d6faa73f26e53d6bee69132530ec170e Mon Sep 17 00:00:00 2001 From: Pedro Beschorner Marin Date: Wed, 13 Jan 2016 15:01:04 +0000 Subject: [PATCH 3/4] Fixed SIP mic reconnection --- .../bigbluebutton/core/apps/UsersApp.scala | 4 +-- .../bigbluebutton/core/apps/UsersModel.scala | 20 +++++------ .../phone/managers/ConnectionManager.as | 34 ++++++++++++------- .../phone/managers/FlashCallManager.as | 9 +++++ .../modules/phone/maps/FlashCallEventMap.mxml | 5 +++ 5 files changed, 47 insertions(+), 25 deletions(-) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala index 95ff877f78..6dd597add8 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala @@ -26,7 +26,7 @@ trait UsersApp { val user = usersModel.getUser(msg.userid) user foreach { u => - if (usersModel.addVoiceConnection(msg.userid)) { + if (usersModel.addGlobalAudioConnection(msg.userid)) { val vu = u.voiceUser.copy(joined = false, talking = false) val uvo = u.copy(listenOnly = true, voiceUser = vu) usersModel.addUser(uvo) @@ -41,7 +41,7 @@ trait UsersApp { val user = usersModel.getUser(msg.userid) user foreach { u => - if (usersModel.removeVoiceConnection(msg.userid)) { + if (usersModel.removeGlobalAudioConnection(msg.userid)) { if (!u.joinedWeb) { val userLeaving = usersModel.removeUser(u.userID) log.info("Not web user. Send user left message. meetingId=" + mProps.meetingID + " userId=" + u.userID + " user=" + u) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersModel.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersModel.scala index 1643e1e45b..9c2f264840 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersModel.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersModel.scala @@ -14,11 +14,11 @@ class UsersModel { private var regUsers = new collection.immutable.HashMap[String, RegisteredUser] - /* When reconnecting SIP audio, users may receive the connection message + /* When reconnecting SIP global audio, users may receive the connection message * before the disconnection message. * This variable is a connection counter that should control this scenario. */ - private var voiceConnectionCounter = new collection.immutable.HashMap[String, Integer] + private var globalAudioConnectionCounter = new collection.immutable.HashMap[String, Integer] private var locked = false private var meetingMuted = false @@ -151,27 +151,27 @@ class UsersModel { } } - def addVoiceConnection(userID: String): Boolean = { - voiceConnectionCounter.get(userID) match { + def addGlobalAudioConnection(userID: String): Boolean = { + globalAudioConnectionCounter.get(userID) match { case Some(vc) => { - voiceConnectionCounter += userID -> (vc + 1) + globalAudioConnectionCounter += userID -> (vc + 1) false } case None => { - voiceConnectionCounter += userID -> 1 + globalAudioConnectionCounter += userID -> 1 true } } } - def removeVoiceConnection(userID: String): Boolean = { - voiceConnectionCounter.get(userID) match { + def removeGlobalAudioConnection(userID: String): Boolean = { + globalAudioConnectionCounter.get(userID) match { case Some(vc) => { if (vc == 1) { - voiceConnectionCounter -= userID + globalAudioConnectionCounter -= userID true } else { - voiceConnectionCounter += userID -> (vc - 1) + globalAudioConnectionCounter += userID -> (vc - 1) false } } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/ConnectionManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/ConnectionManager.as index c276a5f88f..a3eaa9085b 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/ConnectionManager.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/ConnectionManager.as @@ -53,6 +53,7 @@ package org.bigbluebutton.modules.phone.managers { private var closedByUser:Boolean = false; private var reconnecting:Boolean = false; + private var amIListenOnly:Boolean = false; private var dispatcher:Dispatcher; @@ -83,19 +84,24 @@ package org.bigbluebutton.modules.phone.managers { } public function connect():void { - closedByUser = false; - var isTunnelling:Boolean = BBB.initConnectionManager().isTunnelling; - if (isTunnelling) { - uri = uri.replace(/rtmp:/gi, "rtmpt:"); - } - LOGGER.debug("Connecting to uri=[{0}]", [uri]); - NetConnection.defaultObjectEncoding = flash.net.ObjectEncoding.AMF0; - netConnection = new NetConnection(); - netConnection.proxyType = "best"; - netConnection.client = this; - netConnection.addEventListener( NetStatusEvent.NET_STATUS , netStatus ); - netConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); - netConnection.connect(uri, meetingId, externUserId, username); + if (!reconnecting || amIListenOnly) { + closedByUser = false; + var isTunnelling:Boolean = BBB.initConnectionManager().isTunnelling; + if (isTunnelling) { + uri = uri.replace(/rtmp:/gi, "rtmpt:"); + } + LOGGER.debug("Connecting to uri=[{0}]", [uri]); + NetConnection.defaultObjectEncoding = flash.net.ObjectEncoding.AMF0; + netConnection = new NetConnection(); + netConnection.proxyType = "best"; + netConnection.client = this; + netConnection.addEventListener( NetStatusEvent.NET_STATUS , netStatus ); + netConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); + netConnection.connect(uri, meetingId, externUserId, username); + } + if (reconnecting && !amIListenOnly) { + handleConnectionSuccess(); + } } public function disconnect(requestByUser:Boolean):void { @@ -212,12 +218,14 @@ package org.bigbluebutton.modules.phone.managers { // //******************************************************************************************** public function doCall(dialStr:String, listenOnly:Boolean = false):void { + amIListenOnly = listenOnly; LOGGER.debug("in doCall - Calling {0} {1}", [dialStr, listenOnly? "*listen only*": ""]); netConnection.call("voiceconf.call", null, "default", username, dialStr, listenOnly.toString()); } public function doHangUp():void { if (isConnected()) { + amIListenOnly = false; LOGGER.debug("hanging up call"); netConnection.call("voiceconf.hangup", null, "default"); } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/FlashCallManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/FlashCallManager.as index 8cc7ad818f..3d5ba4ee63 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/FlashCallManager.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/FlashCallManager.as @@ -12,6 +12,7 @@ import org.as3commons.logging.util.jsonXify; import org.bigbluebutton.common.Media; import org.bigbluebutton.core.UsersUtil; + import org.bigbluebutton.core.events.VoiceConfEvent; import org.bigbluebutton.main.api.JSLog; import org.bigbluebutton.modules.phone.PhoneOptions; import org.bigbluebutton.modules.phone.events.FlashCallConnectedEvent; @@ -453,5 +454,13 @@ connectionManager.disconnect(true); } } + + public function handleReconnectSIPSucceededEvent():void { + if (state != ON_LISTEN_ONLY_STREAM) { + var e:VoiceConfEvent = new VoiceConfEvent(VoiceConfEvent.EJECT_USER); + e.userid = UsersUtil.getMyUserID(); + dispatcher.dispatchEvent(e); + } + } } } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/maps/FlashCallEventMap.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/maps/FlashCallEventMap.mxml index 77f3c9a13a..2aadf3376b 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/maps/FlashCallEventMap.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/maps/FlashCallEventMap.mxml @@ -28,6 +28,7 @@ with BigBlueButton; if not, see . import mx.events.FlexEvent; import org.bigbluebutton.main.events.MadePresenterEvent; + import org.bigbluebutton.main.events.BBBEvent; import org.bigbluebutton.main.model.users.events.ConnectionFailedEvent; import org.bigbluebutton.modules.phone.events.FlashCallConnectedEvent; import org.bigbluebutton.modules.phone.events.FlashCallDisconnectedEvent; @@ -119,4 +120,8 @@ with BigBlueButton; if not, see . + + + + From e58b527c0f4d8d6a59faeeea64e6c30725f9ba32 Mon Sep 17 00:00:00 2001 From: Richard Alam Date: Thu, 14 Jan 2016 20:08:36 +0000 Subject: [PATCH 4/4] - remove println --- .../red5/client/messaging/ConnectionInvokerService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/messaging/ConnectionInvokerService.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/messaging/ConnectionInvokerService.java index 271d9d9635..501209469d 100755 --- a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/messaging/ConnectionInvokerService.java +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/client/messaging/ConnectionInvokerService.java @@ -276,7 +276,6 @@ public class ConnectionInvokerService { private IConnection getConnection(IScope scope, String userID) { Set conns = new HashSet(); - System.out.println(scope.getClientConnections().size()); for (IConnection conn : scope.getClientConnections()) { String connID = (String) conn.getAttribute("USER_SESSION_ID"); if (connID != null && connID.equals(userID)) {