Merge branch 'pedrobmarin-reconnect-fixes'

This commit is contained in:
Richard Alam 2016-01-14 20:13:08 +00:00
commit 73d00517cf
7 changed files with 114 additions and 34 deletions

View File

@ -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.addGlobalAudioConnection(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.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)
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))
}
}
}
}

View File

@ -14,6 +14,12 @@ class UsersModel {
private var regUsers = new collection.immutable.HashMap[String, RegisteredUser]
/* 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 globalAudioConnectionCounter = new collection.immutable.HashMap[String, Integer]
private var locked = false
private var meetingMuted = false
@ -144,4 +150,34 @@ class UsersModel {
case None =>
}
}
def addGlobalAudioConnection(userID: String): Boolean = {
globalAudioConnectionCounter.get(userID) match {
case Some(vc) => {
globalAudioConnectionCounter += userID -> (vc + 1)
false
}
case None => {
globalAudioConnectionCounter += userID -> 1
true
}
}
}
def removeGlobalAudioConnection(userID: String): Boolean = {
globalAudioConnectionCounter.get(userID) match {
case Some(vc) => {
if (vc == 1) {
globalAudioConnectionCounter -= userID
true
} else {
globalAudioConnectionCounter += userID -> (vc - 1)
false
}
}
case None => {
false
}
}
}
}

View File

@ -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);

View File

@ -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,31 @@ public class ConnectionInvokerService {
}
private IConnection getConnection(IScope scope, String userID) {
Set<IConnection> conns = scope.getClientConnections();
for (IConnection conn : conns) {
Set<IConnection> conns = new HashSet<IConnection>();
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<IConnection> 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) {

View File

@ -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 {
@ -134,7 +140,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));
}
}
@ -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");
}

View File

@ -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);
}
}
}
}

View File

@ -28,6 +28,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
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 <http://www.gnu.org/licenses/>.
<EventHandlers type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}">
<MethodInvoker generator="{FlashCallManager}" method="handleBecomeViewer"/>
</EventHandlers>
<EventHandlers type="{BBBEvent.RECONNECT_SIP_SUCCEEDED_EVENT}">
<MethodInvoker generator="{FlashCallManager}" method="handleReconnectSIPSucceededEvent"/>
</EventHandlers>
</EventMap>