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