diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/BreakoutRoomApp.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/BreakoutRoomApp.scala index 90a1d236a4a1d1da7b00149f13a4406696a73ddb..5ccc1c39e49e7b89cd6e616641153c2a61515292 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/BreakoutRoomApp.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/BreakoutRoomApp.scala @@ -175,7 +175,7 @@ object BreakoutRoomsUtil { } def joinParams(username: String, userId: String, isBreakout: Boolean, breakoutId: String, - password: String, redirect: Boolean): mutable.Map[String, String] = { + password: String, redirect: Boolean): mutable.Map[String, String] = { val params = new collection.mutable.HashMap[String, String] params += "fullName" -> urlEncode(username) params += "userID" -> urlEncode(userId + "-" + breakoutId.substring(breakoutId.lastIndexOf("-") + 1)); diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java index a8c45063fd4ff9252d37f2cdc8a79fa73825c79f..9e90a4a0f7e88a42cb0a3ecabe4d1e185450f2e5 100755 --- a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java +++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java @@ -89,7 +89,7 @@ public class ESLEventListener implements IEslEventListener { System.out.println("User joined voice conference, user=[" + callerIdName + "], conf=[" + confName + "] callerId=[" + callerId + "]"); - VoiceUserJoinedEvent pj = new VoiceUserJoinedEvent(voiceUserId, memberId.toString(), confName, callerId, callerIdName, muted, speaking, ""); + VoiceUserJoinedEvent pj = new VoiceUserJoinedEvent(voiceUserId, memberId.toString(), confName, callerId, callerIdName, muted, speaking, "none"); conferenceEventListener.handleConferenceEvent(pj); } } diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/AppsRedisSubscriberActor.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/AppsRedisSubscriberActor.scala index 66b4cc1f3596299639a6f5280cc0adca5b7812ee..780956206c1c1c95e92197dcb96f0a4b62295d52 100755 --- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/AppsRedisSubscriberActor.scala +++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/endpoint/redis/AppsRedisSubscriberActor.scala @@ -54,7 +54,7 @@ class AppsRedisSubscriberActor(val system: ActorSystem, msgReceiver: RedisMessag } def onPMessage(pmessage: PMessage) { - log.debug(s"pattern message received: $pmessage") + // log.debug(s"pattern message received: $pmessage") val msg = decoder.decodeMessage(pmessage.data) @@ -76,4 +76,4 @@ class AppsRedisSubscriberActor(val system: ActorSystem, msgReceiver: RedisMessag def handleMessage(msg: String) { log.warning("**** TODO: Handle pubsub messages. ****") } -} \ No newline at end of file +} diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/UserJoinedVoiceConfMessage.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/UserJoinedVoiceConfMessage.java index b09101e98c4f9b9bf58331a8e3184c5340cd659e..7c494b425b9107162b5cc0a2dd1ac3c5c7be1bc8 100755 --- a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/UserJoinedVoiceConfMessage.java +++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/UserJoinedVoiceConfMessage.java @@ -72,7 +72,8 @@ public class UserJoinedVoiceConfMessage { && payload.has(CALLER_ID_NAME) && payload.has(CALLER_ID_NUM) && payload.has(MUTED) - && payload.has(TALKING)) { + && payload.has(TALKING) + && payload.has(AVATAR_URL)) { String voiceConfId = payload.get(VOICE_CONF_ID).getAsString(); String voiceUserId = payload.get(VOICE_USER_ID).getAsString(); String userId = payload.get(USER_ID).getAsString(); diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/ConnectionInvokerService.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/ConnectionInvokerService.java index 54b75a028090c50b1bb5fb51bb0802f8c11c05ae..1b5db188969fec113f4f9a23b706e766795d8db7 100755 --- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/ConnectionInvokerService.java +++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/ConnectionInvokerService.java @@ -106,7 +106,7 @@ public class ConnectionInvokerService { for (IConnection conn : conns) { if (conn.isConnected()) { - String connId = (String) conn.getAttribute("INTERNAL_USER_ID"); + String connId = (String) conn.getAttribute("USERID"); log.info("Disconnecting client=[{}] from meeting=[{}]", connId, msg.getMeetingId()); conn.close(); } @@ -200,7 +200,7 @@ public class ConnectionInvokerService { } } - return null; + return null; } public IScope getScope(String meetingID) { diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppService.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppService.java index eee6efcf6831b7c50fd8f93b2418f2fb9bd2621d..b869b89a9cf629cbcc15868aafac595f828694ab 100755 --- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppService.java +++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppService.java @@ -4,19 +4,13 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; - import org.bigbluebutton.app.screenshare.messaging.redis.MessageSender; -//import org.bigbluebutton.app.screenshare.messaging.redis.MessagingConstants; -import org.bigbluebutton.common.messages.AllowUserToShareDesktopRequest; -import org.bigbluebutton.common.messages.MessagingConstants; import org.red5.logging.Red5LoggerFactory; import org.red5.server.api.IConnection; import org.red5.server.api.Red5; import org.slf4j.Logger; - import com.google.gson.Gson; - public class Red5AppService { private static Logger log = Red5LoggerFactory.getLogger(Red5AppService.class, "screenshare"); @@ -45,8 +39,22 @@ public class Red5AppService { Set<IConnection> conns = Red5.getConnectionLocal().getScope().getClientConnections(); for (IConnection conn : conns) { String connUserId = (String) conn.getAttribute("USERID"); - if (connUserId != null && connUserId.equals(userId) && !conn.getSessionId().equals(sessionId)) { + String connSessionId = conn.getSessionId(); + if (connUserId != null && connUserId.equals(userId) && !connSessionId.equals(sessionId)) { conn.removeAttribute("USERID"); + Map<String, Object> logData = new HashMap<String, Object>(); + logData.put("meetingId", meetingId); + logData.put("userId", userId); + logData.put("oldConnId", connSessionId); + logData.put("newConnId", sessionId); + logData.put("event", "removing_defunct_connection"); + logData.put("description", "Removing defunct connection BBB Screenshare."); + + Gson gson = new Gson(); + String logStr = gson.toJson(logData); + + log.info("Removing defunct connection: data={}", logStr); + } } diff --git a/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoApplication.java b/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoApplication.java index b5ead5e55dabf24b3cda153945e48b20dd034c66..f77a058cab9b2f5d90e38317b09d6c2b918e4bfd 100755 --- a/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoApplication.java +++ b/bbb-video/src/main/java/org/bigbluebutton/app/video/VideoApplication.java @@ -20,6 +20,7 @@ package org.bigbluebutton.app.video; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import org.bigbluebutton.red5.pubsub.MessagePublisher; @@ -64,31 +65,57 @@ public class VideoApplication extends MultiThreadedApplicationAdapter { } @Override - public boolean roomConnect(IConnection conn, Object[] params) { - log.info("BBB Video roomConnect"); - String meetingId = ((String) params[0]).toString(); - String userId = ((String) params[1]).toString(); - - Red5.getConnectionLocal().setAttribute("MEETING_ID", meetingId); - Red5.getConnectionLocal().setAttribute("USERID", userId); - + public boolean roomConnect(IConnection connection, Object[] params) { + log.info("BBB Video roomConnect"); + String meetingId = ((String) params[0]).toString(); + String userId = ((String) params[1]).toString(); + + Red5.getConnectionLocal().setAttribute("MEETING_ID", meetingId); + Red5.getConnectionLocal().setAttribute("USERID", userId); + String connType = getConnectionType(Red5.getConnectionLocal().getType()); - String connId = Red5.getConnectionLocal().getSessionId(); - + String sessionId = Red5.getConnectionLocal().getSessionId(); + /** + * Find if there are any other connections owned by this user. If we find one, + * that means that the connection is old and the user reconnected. Clear the + * userId attribute so that messages would not be sent in the defunct connection. + */ + Set<IConnection> conns = Red5.getConnectionLocal().getScope().getClientConnections(); + for (IConnection conn : conns) { + String connUserId = (String) conn.getAttribute("USERID"); + String connSessionId = conn.getSessionId(); + if (connUserId != null && connUserId.equals(userId) && !connSessionId.equals(sessionId)) { + conn.removeAttribute("USERID"); + Map<String, Object> logData = new HashMap<String, Object>(); + logData.put("meetingId", meetingId); + logData.put("userId", userId); + logData.put("oldConnId", connSessionId); + logData.put("newConnId", sessionId); + logData.put("event", "removing_defunct_connection"); + logData.put("description", "Removing defunct connection BBB Video."); + + Gson gson = new Gson(); + String logStr = gson.toJson(logData); + + log.info("Removing defunct connection: data={}", logStr); + + } + } + Map<String, Object> logData = new HashMap<String, Object>(); logData.put("meetingId", meetingId); logData.put("userId", userId); logData.put("connType", connType); - logData.put("connId", connId); + logData.put("connId", sessionId); logData.put("event", "user_joining_bbb_video"); logData.put("description", "User joining BBB Video."); - + Gson gson = new Gson(); - String logStr = gson.toJson(logData); - + String logStr = gson.toJson(logData); + log.info("User joining bbb-video: data={}", logStr); - - return super.roomConnect(conn, params); + + return super.roomConnect(connection, params); } private String getConnectionType(String connType) { diff --git a/bbb.sh b/bbb.sh index 5df1480b4923590a11126fc2c903ede8faf4a933..5c89021d275c4012f2e3a6242a4777b52d37dda8 100755 --- a/bbb.sh +++ b/bbb.sh @@ -7,7 +7,7 @@ BBB_DIR=$(pwd) cd $BBB_DIR -DESKSHARE=$BBB_DIR/deskshare +DESKSHARE=$BBB_DIR/bbb-screenshare VOICE=$BBB_DIR/bbb-voice VIDEO=$BBB_DIR/bbb-video APPS=$BBB_DIR/bigbluebutton-apps @@ -28,10 +28,8 @@ gradle resolveDeps gradle clean war deploy echo "Building deskshare" -cd $DESKSHARE -gradle resolveDeps cd $DESKSHARE/app -gradle clean war deploy +./deploy.sh cd $BBB_DIR 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 ada2122d5d8a64196da4e58999b40f294f29faa9..0c09f008cd51a82b0a2669f02c0ae6f12be98e01 100755 --- a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/BigBlueButtonApplication.java +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/BigBlueButtonApplication.java @@ -42,8 +42,6 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter { private ConnectionInvokerService connInvokerService; private MessagePublisher red5InGW; - private final UserConnectionMapper userConnections = new UserConnectionMapper(); - private final String APP = "BBB"; private final String CONN = "RED5-"; @@ -127,7 +125,36 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter { } String userId = internalUserID; - String sessionId = CONN + userId; + String sessionId = Red5.getConnectionLocal().getSessionId(); + String connType = getConnectionType(Red5.getConnectionLocal().getType()); + + /** + * Find if there are any other connections owned by this user. If we find one, + * that means that the connection is old and the user reconnected. Clear the + * userId attribute so that messages would not be sent in the defunct connection. + */ + Set<IConnection> conns = Red5.getConnectionLocal().getScope().getClientConnections(); + for (IConnection conn : conns) { + String connUserId = (String) conn.getAttribute("INTERNAL_USER_ID"); + String connSessionId = conn.getSessionId(); + if (connUserId != null && connUserId.equals(userId) && !connSessionId.equals(sessionId)) { + conn.removeAttribute("INTERNAL_USER_ID"); + Map<String, Object> logData = new HashMap<String, Object>(); + logData.put("meetingId", room); + logData.put("userId", userId); + logData.put("oldConnId", connSessionId); + logData.put("newConnId", sessionId); + logData.put("event", "removing_defunct_connection"); + logData.put("description", "Removing defunct connection BBB Apps."); + + Gson gson = new Gson(); + String logStr = gson.toJson(logData); + + log.info("Removing defunct connection: data={}", logStr); + } + } + + BigBlueButtonSession bbbSession = new BigBlueButtonSession(room, internalUserID, username, role, voiceBridge, record, externalUserID, muted, sessionId); connection.setAttribute(Constants.SESSION, bbbSession); @@ -140,8 +167,7 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter { red5InGW.initAudioSettings(room, internalUserID, muted); String meetingId = bbbSession.getRoom(); - - String connType = getConnectionType(Red5.getConnectionLocal().getType()); + String userFullname = bbbSession.getUsername(); String connId = Red5.getConnectionLocal().getSessionId(); @@ -165,9 +191,7 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter { String logStr = gson.toJson(logData); log.info("User joining bbb-apps: data={}", logStr); - - userConnections.addUserConnection(userId, connId); - + return super.roomConnect(connection, params); } @@ -186,8 +210,7 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter { public void roomDisconnect(IConnection conn) { String remoteHost = Red5.getConnectionLocal().getRemoteAddress(); - int remotePort = Red5.getConnectionLocal().getRemotePort(); - String clientId = Red5.getConnectionLocal().getClient().getId(); + int remotePort = Red5.getConnectionLocal().getRemotePort(); BigBlueButtonSession bbbSession = (BigBlueButtonSession) Red5.getConnectionLocal().getAttribute(Constants.SESSION); @@ -212,15 +235,9 @@ public class BigBlueButtonApplication extends MultiThreadedApplicationAdapter { Gson gson = new Gson(); String logStr = gson.toJson(logData); - - boolean removeUser = userConnections.userDisconnected(userId, connId); - - if (removeUser) { - log.info("User leaving bbb-apps: data={}", logStr); - red5InGW.userLeft(bbbSession.getRoom(), getBbbSession().getInternalUserID(), sessionId); - } else { - log.info("User not leaving bbb-apps but just disconnected: data={}", logStr); - } + + log.info("User leaving bbb-apps: data={}", logStr); + red5InGW.userLeft(bbbSession.getRoom(), getBbbSession().getInternalUserID(), sessionId); super.roomDisconnect(conn); } 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 8952dbf3774f9afe3888f8328bd54f6a03b63f90..0ce096841767dd6d51ebc08023cdf18277e9f904 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 @@ -175,13 +175,13 @@ public class ConnectionInvokerService { log.trace("Handle direct message: " + msg.getMessageName() + " msg=" + json); } - final String sessionId = CONN + msg.getUserID(); + final String userId = msg.getUserID(); Runnable sender = new Runnable() { public void run() { IScope meetingScope = getScope(msg.getMeetingID()); if (meetingScope != null) { - IConnection conn = getConnection(meetingScope, sessionId); + IConnection conn = getConnection(meetingScope, userId); if (conn != null) { if (conn.isConnected()) { List<Object> params = new ArrayList<Object>(); @@ -197,7 +197,7 @@ public class ConnectionInvokerService { ServiceUtils.invokeOnConnection(conn, "onMessageFromServer", params.toArray()); } } else { - log.info("Cannot send message=[" + msg.getMessageName() + "] to [" + sessionId + log.info("Cannot send message=[" + msg.getMessageName() + "] to [" + userId + "] as no such session on meeting=[" + msg.getMeetingID() + "]"); } } @@ -217,12 +217,12 @@ public class ConnectionInvokerService { long timeLeft = endNanos - System.nanoTime(); f.get(timeLeft, TimeUnit.NANOSECONDS); } catch (ExecutionException e) { - log.warn("ExecutionException while sending direct message on connection[" + sessionId + "]"); + log.warn("ExecutionException while sending direct message on connection[" + userId + "]"); } catch (InterruptedException e) { - log.warn("Interrupted exception while sending direct message on connection[" + sessionId + "]"); + log.warn("Interrupted exception while sending direct message on connection[" + userId + "]"); Thread.currentThread().interrupt(); } catch (TimeoutException e) { - log.warn("Timeout exception while sending direct message on connection[" + sessionId + "]"); + log.warn("Timeout exception while sending direct message on connection[" + userId + "]"); f.cancel(true); } } @@ -275,31 +275,15 @@ public class ConnectionInvokerService { } private IConnection getConnection(IScope scope, String userID) { - Set<IConnection> conns = new HashSet<IConnection>(); for (IConnection conn : scope.getClientConnections()) { - String connID = (String) conn.getAttribute("USER_SESSION_ID"); + String connID = (String) conn.getAttribute("INTERNAL_USER_ID"); if (connID != null && connID.equals(userID)) { - conns.add(conn); + return conn; } } - 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; + log.warn("Failed to get connection for userId = " + userID); + return null; } public IScope getScope(String meetingID) { diff --git a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/redis/RedisPubSubMessageHandler.java b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/redis/RedisPubSubMessageHandler.java index 1f9174d8d6ff5bf44c6bbe1927e9eeb3cecc94b5..81f52151f48b52636f1cdc6c1da932b98cfeda24 100755 --- a/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/redis/RedisPubSubMessageHandler.java +++ b/bigbluebutton-apps/src/main/java/org/bigbluebutton/red5/pubsub/redis/RedisPubSubMessageHandler.java @@ -11,11 +11,11 @@ import org.bigbluebutton.red5.client.CaptionClientMessageSender; import org.bigbluebutton.red5.client.DeskShareMessageSender; import org.bigbluebutton.red5.client.messaging.ConnectionInvokerService; import org.bigbluebutton.red5.monitoring.BbbAppsIsKeepAliveHandler; -import org.red5.logging.Red5LoggerFactory; -import org.slf4j.Logger; +import org.red5.logging.Red5LoggerFactory; +import org.slf4j.Logger; public class RedisPubSubMessageHandler implements MessageHandler { - private static Logger log = Red5LoggerFactory.getLogger(RedisPubSubMessageHandler.class, "bigbluebutton"); + private static Logger log = Red5LoggerFactory.getLogger(RedisPubSubMessageHandler.class, "bigbluebutton"); private ConnectionInvokerService service; private UserClientMessageSender userMessageSender; @@ -54,7 +54,6 @@ public class RedisPubSubMessageHandler implements MessageHandler { } else if (channel.equalsIgnoreCase(MessagingConstants.FROM_MEETING_CHANNEL)) { meetingMessageSender.handleMeetingMessage(message); } else if (channel.equalsIgnoreCase(MessagingConstants.FROM_USERS_CHANNEL)) { - log.info("trace 0 : " + message); userMessageSender.handleUsersMessage(message); } else if (channel.equalsIgnoreCase(MessagingConstants.FROM_WHITEBOARD_CHANNEL)) { whiteboardMessageSender.handleWhiteboardMessage(message);