diff --git a/akka-bbb-apps/src/main/java/org/bigbluebutton/core/api/IBigBlueButtonInGW.java b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/api/IBigBlueButtonInGW.java
index 957eca1d1f00b9e4f1e49fdfbec3fe878c013549..3964e884ab78986f6c443b0f701dc2a5d9be3779 100755
--- a/akka-bbb-apps/src/main/java/org/bigbluebutton/core/api/IBigBlueButtonInGW.java
+++ b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/api/IBigBlueButtonInGW.java
@@ -40,6 +40,7 @@ public interface IBigBlueButtonInGW {
 	void userLeft(String meetingID, String userID, String sessionId);
 	void userJoin(String meetingID, String userID, String authToken);
 	void getCurrentPresenter(String meetingID, String requesterID);
+    void checkIfAllowedToShareDesktop(String meetingID, String userID);
 	void assignPresenter(String meetingID, String newPresenterID, String newPresenterName, String assignedBy);
 	void setRecordingStatus(String meetingId, String userId, Boolean recording);
 	void getRecordingStatus(String meetingId, String userId);
diff --git a/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/UsersMessageReceiver.java b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/UsersMessageReceiver.java
index 44382376de93478aab8b7379301f3d715fc721ad..a43ec10c7e3bbd69db0a21cce621b4318ca56a01 100755
--- a/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/UsersMessageReceiver.java
+++ b/akka-bbb-apps/src/main/java/org/bigbluebutton/core/pubsub/receivers/UsersMessageReceiver.java
@@ -33,6 +33,9 @@ public class UsersMessageReceiver implements MessageHandler{
 					  case UserLeavingMessage.USER_LEAVING:
 						  processUserLeavingMessage(message);
 						  break;
+					  case AllowUserToShareDesktopRequest.NAME:
+						  processAllowUserToShareDesktopRequest(message);
+						  break;
 					  case AssignPresenterRequestMessage.ASSIGN_PRESENTER_REQUEST:
 						  processAssignPresenterRequestMessage(message);
 						  break;
@@ -193,7 +196,14 @@ public class UsersMessageReceiver implements MessageHandler{
 			  bbbInGW.userLeft(ulm.meetingId, ulm.userId, ulm.meetingId);
 		  }		
 	}
-	
+
+    private void processAllowUserToShareDesktopRequest(String message) {
+        AllowUserToShareDesktopRequest msg = AllowUserToShareDesktopRequest.fromJson(message);
+        if (msg != null) {
+            bbbInGW.checkIfAllowedToShareDesktop(msg.meetingId, msg.userId);
+        }
+    }
+
 	private void processAssignPresenterRequestMessage(String message) {
 		AssignPresenterRequestMessage apm = AssignPresenterRequestMessage.fromJson(message);
 		if (apm != null) {
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/BigBlueButtonInGW.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/BigBlueButtonInGW.scala
index 508011e47fea43eda6fed683a05c162a5915688d..37eacf898d8559f4889402466c21ad712467d868 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/BigBlueButtonInGW.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/BigBlueButtonInGW.scala
@@ -243,6 +243,11 @@ class BigBlueButtonInGW(
     eventBus.publish(BigBlueButtonEvent(meetingID, new UserJoining(meetingID, userID, authToken)))
   }
 
+  def checkIfAllowedToShareDesktop(meetingID: String, userID: String): Unit = {
+    eventBus.publish(BigBlueButtonEvent(meetingID, AllowUserToShareDesktop(meetingID: String,
+      userID: String)))
+  }
+
   def assignPresenter(meetingID: String, newPresenterID: String, newPresenterName: String, assignedBy: String): Unit = {
     eventBus.publish(BigBlueButtonEvent(meetingID, new AssignPresenter(meetingID, newPresenterID, newPresenterName, assignedBy)))
   }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/LiveMeeting.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/LiveMeeting.scala
index 8d5e313e3fbaeaf4a1e72234820d7d90e65d649b..51da9d7816ca4174ed58b84f2ee5ab579195f7e0 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/LiveMeeting.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/LiveMeeting.scala
@@ -125,6 +125,16 @@ class LiveMeeting(val mProps: MeetingProperties,
     outGW.send(new DisconnectAllUsers(msg.meetingId))
   }
 
+  def handleAllowUserToShareDesktop(msg: AllowUserToShareDesktop): Unit = {
+    usersModel.getCurrentPresenter() match {
+      case Some(curPres) => {
+        val allowed = msg.userID equals (curPres.userID)
+        outGW.send(AllowUserToShareDesktopOut(msg.meetingID, msg.userID, allowed))
+      }
+      case None => // do nothing
+    }
+  }
+
   def handleVoiceConfRecordingStartedMessage(msg: VoiceConfRecordingStartedMessage) {
     if (msg.recording) {
       meetingModel.setVoiceRecordingFilename(msg.recordStream)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MeetingActor.scala
index 72d17227ea32d9700456ccb0fe16db0d605d77ff..c3a67357ddf95c55d19cc5f7dc4fa4bcf0bdc683 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MeetingActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MeetingActor.scala
@@ -105,6 +105,7 @@ class MeetingActor(val mProps: MeetingProperties,
     case msg: UserJoining => liveMeeting.handleUserJoin(msg)
     case msg: UserLeaving => liveMeeting.handleUserLeft(msg)
     case msg: AssignPresenter => liveMeeting.handleAssignPresenter(msg)
+    case msg: AllowUserToShareDesktop => liveMeeting.handleAllowUserToShareDesktop(msg)
     case msg: GetUsers => liveMeeting.handleGetUsers(msg)
     case msg: ChangeUserStatus => liveMeeting.handleChangeUserStatus(msg)
     case msg: EjectUserFromMeeting => liveMeeting.handleEjectUserFromMeeting(msg)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSenderActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSenderActor.scala
index 46c7bda4ceb3205ecf93e76b3fb806a09390443c..e587c3c24011d4b15c3bd9fefec524eb6627766f 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSenderActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/MessageSenderActor.scala
@@ -15,7 +15,9 @@ import org.bigbluebutton.core.pubsub.senders.CaptionMessageToJsonConverter
 import org.bigbluebutton.core.pubsub.senders.DeskShareMessageToJsonConverter
 import org.bigbluebutton.common.messages.GetPresentationInfoReplyMessage
 import org.bigbluebutton.common.messages.PresentationRemovedMessage
+import org.bigbluebutton.common.messages.AllowUserToShareDesktopReply
 import org.bigbluebutton.core.apps.Page
+
 import collection.JavaConverters._
 import scala.collection.JavaConversions._
 import org.bigbluebutton.core.apps.SimplePollResultOutVO
@@ -31,6 +33,7 @@ import org.bigbluebutton.common.messages.LockLayoutMessage
 import org.bigbluebutton.core.pubsub.senders.WhiteboardMessageToJsonConverter
 import org.bigbluebutton.common.converters.ToJsonEncoder
 import org.bigbluebutton.common.messages.TransferUserToVoiceConfRequestMessage
+import org.bigbluebutton.core
 
 object MessageSenderActor {
   def props(msgSender: MessageSender): Props =
@@ -82,6 +85,7 @@ class MessageSenderActor(val service: MessageSender)
     case msg: MeetingMuted => handleMeetingMuted(msg)
     case msg: MeetingState => handleMeetingState(msg)
     case msg: DisconnectAllUsers => handleDisconnectAllUsers(msg)
+    case msg: AllowUserToShareDesktopOut => handleAllowUserToShareDesktopOut(msg)
     case msg: DisconnectUser => handleDisconnectUser(msg)
     case msg: PermissionsSettingInitialized => handlePermissionsSettingInitialized(msg)
     case msg: NewPermissionsSetting => handleNewPermissionsSetting(msg)
@@ -535,6 +539,13 @@ class MessageSenderActor(val service: MessageSender)
     service.send(MessagingConstants.FROM_MEETING_CHANNEL, json)
   }
 
+  private def handleAllowUserToShareDesktopOut(msg: AllowUserToShareDesktopOut): Unit = {
+    val obj = new AllowUserToShareDesktopReply(msg.meetingID, msg.userID, msg.allowed,
+      TimestampGenerator.generateTimestamp)
+    val json = obj.toJson()
+    service.send(MessagingConstants.FROM_MEETING_CHANNEL, json)
+  }
+
   private def handlePermissionsSettingInitialized(msg: PermissionsSettingInitialized) {
     val json = UsersMessageToJsonConverter.permissionsSettingInitializedToJson(msg)
     service.send(MessagingConstants.FROM_MEETING_CHANNEL, json)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala
index 2fb1ab82d96e65946c8b1b9b3353af374fe7dd86..bacab94d0baf2dc984fcdc47a894b047f4101044 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/InMessages.scala
@@ -90,6 +90,7 @@ case class ChangeUserStatus(meetingID: String, userID: String, status: String, v
 case class AssignPresenter(meetingID: String, newPresenterID: String, newPresenterName: String, assignedBy: String) extends InMessage
 case class SetRecordingStatus(meetingID: String, userId: String, recording: Boolean) extends InMessage
 case class GetRecordingStatus(meetingID: String, userId: String) extends InMessage
+case class AllowUserToShareDesktop(meetingID: String, userID: String) extends InMessage
 
 //////////////////////////////////////////////////////////////////////////////////
 // Chat
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/OutMessages.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/OutMessages.scala
index 7ae93d2803377569b470a83c0660aed7c64f4baa..d3c9588ac5ec22414c4041def951bf4d0d8e905d 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/OutMessages.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/api/OutMessages.scala
@@ -73,6 +73,7 @@ case class EjectVoiceUser(meetingID: String, recorded: Boolean, requesterID: Str
 case class TransferUserToMeeting(voiceConfId: String, targetVoiceConfId: String, userId: String) extends IOutMessage
 case class UserJoinedVoice(meetingID: String, recorded: Boolean, confNum: String, user: UserVO) extends IOutMessage
 case class UserLeftVoice(meetingID: String, recorded: Boolean, confNum: String, user: UserVO) extends IOutMessage
+case class AllowUserToShareDesktopOut(meetingID: String, userID: String, allowed: Boolean) extends IOutMessage
 
 // Voice
 case class IsMeetingMutedReply(meetingID: String, recorded: Boolean, requesterID: String, meetingMuted: Boolean) extends IOutMessage
diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/AllowUserToShareDesktopReply.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/AllowUserToShareDesktopReply.java
new file mode 100644
index 0000000000000000000000000000000000000000..cbe769de7d684c5a052c2ecfc824c8ee6d0cf058
--- /dev/null
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/AllowUserToShareDesktopReply.java
@@ -0,0 +1,66 @@
+package org.bigbluebutton.common.messages;
+
+import java.util.HashMap;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+public class AllowUserToShareDesktopReply implements ISubscribedMessage {
+    public static final String NAME = "AllowUserToShareDesktopReply";
+    public static final String VERSION = "0.0.1";
+
+    public static final String TIMESTAMP = "timestamp";
+    public static final String MEETING_ID = "meeting_id";
+    public static final String USER_ID = "user_id";
+    public static final String ALLOWED = "allowed";
+
+    public final Long timestamp;
+    public final String userId;
+    public final String meetingId;
+    public final Boolean allowed;
+
+    public AllowUserToShareDesktopReply(String meetingId, String userId,
+     Boolean allowed, Long timestamp) {
+        this.meetingId = meetingId;
+        this.userId = userId;
+        this.allowed = allowed;
+        this.timestamp = timestamp;
+    }
+
+    public String toJson() {
+        HashMap<String, Object> payload = new HashMap<String, Object>();
+        payload.put(TIMESTAMP, timestamp);
+        payload.put(MEETING_ID, meetingId);
+        payload.put(USER_ID, userId);
+        payload.put(ALLOWED, allowed);
+
+        java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(NAME, VERSION, null);
+        return MessageBuilder.buildJson(header, payload);
+    }
+
+    public static AllowUserToShareDesktopReply fromJson(String message) {
+        JsonParser parser = new JsonParser();
+        JsonObject obj = (JsonObject) parser.parse(message);
+        if (obj.has("header") && obj.has("payload")) {
+            JsonObject header = (JsonObject) obj.get("header");
+            JsonObject payload = (JsonObject) obj.get("payload");
+
+            if (header.has("name")) {
+                String messageName = header.get("name").getAsString();
+                if (NAME.equals(messageName)) {
+
+                    if (payload.has(TIMESTAMP) && payload.has(MEETING_ID)
+                            && payload.has(USER_ID) && payload.has(ALLOWED)) {
+                        Long timestamp = payload.get(TIMESTAMP).getAsLong();
+                        String meetingId = payload.get(MEETING_ID).getAsString();
+                        String userId = payload.get(USER_ID).getAsString();
+                        Boolean allowed = payload.get(ALLOWED).getAsBoolean();
+                        return new AllowUserToShareDesktopReply(meetingId, userId, allowed,
+                                timestamp);
+                    }
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/AllowUserToShareDesktopRequest.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/AllowUserToShareDesktopRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f35fb98cc12114c109b3d6cce9c5e221dff61f48
--- /dev/null
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/AllowUserToShareDesktopRequest.java
@@ -0,0 +1,58 @@
+package org.bigbluebutton.common.messages;
+
+import java.util.HashMap;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+public class AllowUserToShareDesktopRequest implements ISubscribedMessage {
+    public static final String NAME = "AllowUserToShareDesktopRequest";
+    public static final String VERSION = "0.0.1";
+
+    public static final String TIMESTAMP = "timestamp";
+    public static final String MEETING_ID = "meeting_id";
+    public static final String USER_ID = "user_id";
+
+    public final Long timestamp;
+    public final String userId;
+    public final String meetingId;
+
+    public AllowUserToShareDesktopRequest(String meetingId, String userId, Long timestamp) {
+        this.meetingId = meetingId;
+        this.userId = userId;
+        this.timestamp = timestamp;
+    }
+
+    public String toJson() {
+        HashMap<String, Object> payload = new HashMap<String, Object>();
+        payload.put(TIMESTAMP, timestamp);
+        payload.put(MEETING_ID, meetingId);
+        payload.put(USER_ID, userId);
+
+        java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(NAME, VERSION, null);
+        return MessageBuilder.buildJson(header, payload);
+    }
+
+    public static AllowUserToShareDesktopRequest fromJson(String message) {
+        JsonParser parser = new JsonParser();
+        JsonObject obj = (JsonObject) parser.parse(message);
+        if (obj.has("header") && obj.has("payload")) {
+            JsonObject header = (JsonObject) obj.get("header");
+            JsonObject payload = (JsonObject) obj.get("payload");
+
+            if (header.has("name")) {
+                String messageName = header.get("name").getAsString();
+                if (NAME.equals(messageName)) {
+
+                    if (payload.has(TIMESTAMP) && payload.has(MEETING_ID) && payload.has(USER_ID)) {
+                        Long timestamp = payload.get(TIMESTAMP).getAsLong();
+                        String meetingId = payload.get(MEETING_ID).getAsString();
+                        String userId = payload.get(USER_ID).getAsString();
+                        return new AllowUserToShareDesktopRequest(meetingId, userId, timestamp);
+                    }
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/MeetingCreatedMessage.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/MeetingCreatedMessage.java
new file mode 100755
index 0000000000000000000000000000000000000000..02db9d0a6db17c60fdd7515340f7680f687d0193
--- /dev/null
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/MeetingCreatedMessage.java
@@ -0,0 +1,49 @@
+package org.bigbluebutton.common.messages;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import java.util.HashMap;
+
+public class MeetingCreatedMessage implements ISubscribedMessage {
+	public static final String MEETING_CREATED = "meeting_created_message";
+	public final String VERSION = "0.0.1";
+
+	public final String meetingId;
+
+	public MeetingCreatedMessage(String meetingID) {
+		this.meetingId = meetingID;
+	}
+
+	public String toJson() {
+		HashMap<String, Object> payload = new HashMap<String, Object>();
+		payload.put(Constants.MEETING_ID, meetingId);
+
+		HashMap<String, Object> header = MessageBuilder.buildHeader(MEETING_CREATED, VERSION, null);
+
+		return MessageBuilder.buildJson(header, payload);
+	}
+
+	public static MeetingCreatedMessage fromJson(String message) {
+		JsonParser parser = new JsonParser();
+		JsonObject obj = (JsonObject) parser.parse(message);
+
+		if (obj.has("header") && obj.has("payload")) {
+			JsonObject header = (JsonObject) obj.get("header");
+			JsonObject payload = (JsonObject) obj.get("payload");
+
+			if (header.has("name")) {
+				String messageName = header.get("name").getAsString();
+				if (MEETING_CREATED.equals(messageName)) {
+					if (payload.has(Constants.MEETING_ID)) {
+						String meetingId = payload.get(Constants.MEETING_ID).getAsString();
+
+						return new MeetingCreatedMessage(meetingId);
+					}
+				}
+			}
+		}
+
+		return null;
+	}
+}
diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/MeetingDestroyedMessage.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/MeetingDestroyedMessage.java
new file mode 100755
index 0000000000000000000000000000000000000000..689233dc8e7f04fe9423e51d2f5e63d8f25c87ef
--- /dev/null
+++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/MeetingDestroyedMessage.java
@@ -0,0 +1,49 @@
+package org.bigbluebutton.common.messages;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import java.util.HashMap;
+
+public class MeetingDestroyedMessage implements ISubscribedMessage {
+	public static final String NAME = "meeting_destroyed_event";
+	public final String VERSION = "0.0.1";
+
+	public final String meetingId;
+
+	public MeetingDestroyedMessage(String meetingID) {
+		this.meetingId = meetingID;
+	}
+
+	public String toJson() {
+		HashMap<String, Object> payload = new HashMap<String, Object>();
+		payload.put(Constants.MEETING_ID, meetingId);
+
+		HashMap<String, Object> header = MessageBuilder.buildHeader(NAME, VERSION, null);
+
+		return MessageBuilder.buildJson(header, payload);
+	}
+
+	public static MeetingDestroyedMessage fromJson(String message) {
+		JsonParser parser = new JsonParser();
+		JsonObject obj = (JsonObject) parser.parse(message);
+
+		if (obj.has("header") && obj.has("payload")) {
+			JsonObject header = (JsonObject) obj.get("header");
+			JsonObject payload = (JsonObject) obj.get("payload");
+
+			if (header.has("name")) {
+				String messageName = header.get("name").getAsString();
+				if (NAME.equals(messageName)) {
+					if (payload.has(Constants.MEETING_ID)) {
+						String meetingId = payload.get(Constants.MEETING_ID).getAsString();
+
+						return new MeetingDestroyedMessage(meetingId);
+					}
+				}
+			}
+		}
+
+		return null;
+	}
+}
diff --git a/bbb-screenshare/app/build.sbt b/bbb-screenshare/app/build.sbt
index 1443d205fa233f7c3e902c0f5833c97651401c49..c1a489f77218274e048177bbdcf3600de18b039b 100644
--- a/bbb-screenshare/app/build.sbt
+++ b/bbb-screenshare/app/build.sbt
@@ -7,7 +7,6 @@ organization := "org.bigbluebutton"
 
 version := "0.0.1"
 
-//scalaVersion  := "2.11.6"
 scalaVersion  := "2.11.7"
 
 scalacOptions ++= Seq(
@@ -16,7 +15,7 @@ scalacOptions ++= Seq(
   "-Xlint",
   "-Ywarn-dead-code",
   "-language:_",
-  "-target:jvm-1.8", //TODO this was 1.7
+  "-target:jvm-1.8",
   "-encoding", "UTF-8"
 )
 
@@ -34,7 +33,6 @@ publishTo := Some(Resolver.file("file",  new File(Path.userHome.absolutePath+"/d
 retrieveManaged := true
 
 libraryDependencies ++= {
-//  val akkaVersion  = "2.3.11"
     val akkaVersion  = "2.4.2"
     val springVersion = "4.2.5.RELEASE"
   Seq(
@@ -49,15 +47,16 @@ libraryDependencies ++= {
     "commons-codec"             %  "commons-codec"     % "1.8",
         "redis.clients"             %  "jedis"             % "2.7.2",
     //    "org.apache.commons"        %  "commons-lang3"     % "3.2",
+    "org.apache.commons"        %  "commons-pool2"     % "2.3",
     "org.red5"                  %  "red5-server"       % "1.0.7-M10",
-    "com.google.code.gson"      %  "gson"              % "1.7.1",
-
+    "com.google.code.gson"      %  "gson"              % "2.5",
     "org.springframework"       %  "spring-web"        % springVersion,
     "org.springframework"       %  "spring-beans"      % springVersion,
     "org.springframework"       %  "spring-context"    % springVersion,
     "org.springframework"       %  "spring-core"       % springVersion,
     "org.springframework"       %  "spring-webmvc"     % springVersion,
     "org.springframework"       %  "spring-aop"        % springVersion,
+    "org.bigbluebutton"         %  "bbb-common-message"% "0.0.18-SNAPSHOT",
     "javax.servlet"             %  "servlet-api"       % "2.5"
 
 
@@ -92,4 +91,3 @@ daemonUser in Linux := user
 
 // group which will execute the application
 daemonGroup in Linux := group
-
diff --git a/bbb-screenshare/app/deploy.sh b/bbb-screenshare/app/deploy.sh
index 5c1e81a5afa1c932503847ef6e58f379ce6f831a..47103026e68002accff2248f344b9def3ad109df 100755
--- a/bbb-screenshare/app/deploy.sh
+++ b/bbb-screenshare/app/deploy.sh
@@ -1,8 +1,3 @@
-##!/usr/bin/env bash
-#sudo chmod -R 777 /usr/share/red5/webapps
-#gradle clean war deploy
-#sudo chmod -R 777 /usr/share/red5/webapps
-
 #!/bin/bash
 # deploying 'screenshare' to /usr/share/red5/webapps
 
@@ -20,9 +15,11 @@ sudo cp ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/bbb-sc
  ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/scala-library-* \
  ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/akka-* \
  ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/config-1.3.0.jar \
- ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/gson-1.7.1.jar \
+ ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/gson-2.5.jar \
  ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/jedis-2.7.2.jar \
+ ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/commons-pool2-2.3.jar \
  ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/spring-webmvc-4.2.5.RELEASE.jar  \
+ ~/dev/bigbluebutton/bbb-screenshare/app/target/webapp/WEB-INF/lib/bbb-common-message-0.0.18-SNAPSHOT.jar \
   /usr/share/red5/webapps/screenshare/WEB-INF/lib/
 
 
@@ -43,3 +40,8 @@ sudo chown -R red5:red5 /usr/share/red5/webapps/screenshare
 
 # TODO change the owner username to 'firstuser'
 
+# // Dev only
+#sudo service red5 restart
+#sudo service tomcat7 restart
+#sudo service bbb-apps-akka restart
+
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/IScreenShareApplication.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/IScreenShareApplication.java
index 1923906f319605d1f890028dd55d22c0dcfccb07..0772e4f0d2660869b75a65e90337da8b71661fbd 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/IScreenShareApplication.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/IScreenShareApplication.java
@@ -1,10 +1,17 @@
 package org.bigbluebutton.app.screenshare;
 
+
+import org.bigbluebutton.app.screenshare.events.IsScreenSharingResponse;
+
 public interface IScreenShareApplication {
   
-  IsScreenSharingResponse isScreenSharing(String meetingId);
+
   ScreenShareInfoResponse getScreenShareInfo(String meetingId, String token);
-  StartShareRequestResponse startShareRequest(String meetingId, String userId, Boolean record);
+  SharingStatus getSharingStatus(String meetingId, String streamId);
+  Boolean recordStream(String meetingId, String streamId);
+
+  void isScreenSharing(String meetingId, String userId);
+  void startShareRequest(String meetingId, String userId, Boolean record);
   void pauseShareRequest(String meetingId, String userId, String streamId);
   void restartShareRequest(String meetingId, String userId);
   void stopShareRequest(String meetingId, String streamId);
@@ -13,8 +20,8 @@ public interface IScreenShareApplication {
   void sharingStarted(String meetingId, String streamId, Integer width, Integer height);
   void sharingStopped(String meetingId, String streamId);
   void updateShareStatus(String meetingId, String streamId, Integer seqNum);
-  SharingStatus getSharingStatus(String meetingId, String streamId);
-  Boolean recordStream(String meetingId, String streamId);
   void userDisconnected(String meetingId, String userId);
   void userConnected(String meetingId, String userId);
+  void meetingHasEnded(String meetingId);
+  void meetingCreated(String meetingId);
 }
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/IsScreenSharingResponse.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/IsScreenSharingResponse.java
deleted file mode 100755
index 2cab8dea76454735b89183d102ca432746c6d837..0000000000000000000000000000000000000000
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/IsScreenSharingResponse.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.bigbluebutton.app.screenshare;
-
-public class IsScreenSharingResponse {
-
-  public final StreamInfo info;
-  public final Error error;
-  
-  public IsScreenSharingResponse(StreamInfo info, Error error) {
-    this.info = info;
-    this.error = error;
-  }
-}
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/StartShareRequestResponse.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/StartShareRequestResponse.java
deleted file mode 100755
index 36faab1a3cc95aefc28416ec4e55ee103a57606d..0000000000000000000000000000000000000000
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/StartShareRequestResponse.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.bigbluebutton.app.screenshare;
-
-public class StartShareRequestResponse {
-
-  public final String token;
-  public final String jnlp;
-  public final String streamId;
-  public final Error error;
-  
-  public StartShareRequestResponse(String token, String jnlp, String streamId, Error error) {
-    this.token = token;
-    this.jnlp = jnlp;
-    this.streamId = streamId;
-    this.error = error;
-  }
-}
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/events/IsScreenSharingResponse.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/events/IsScreenSharingResponse.java
new file mode 100755
index 0000000000000000000000000000000000000000..699409caca63bfbffe5f33160fd5ebacbbf73cfe
--- /dev/null
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/events/IsScreenSharingResponse.java
@@ -0,0 +1,18 @@
+package org.bigbluebutton.app.screenshare.events;
+
+import org.bigbluebutton.app.screenshare.Error;
+import org.bigbluebutton.app.screenshare.StreamInfo;
+
+public class IsScreenSharingResponse implements IEvent {
+
+  public final String meetingId;
+  public final String userId;
+
+  public final StreamInfo info;
+  
+  public IsScreenSharingResponse(String meetingId, String userId, StreamInfo info) {
+    this.meetingId = meetingId;
+    this.userId = userId;
+    this.info = info;
+  }
+}
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/events/StartShareRequestFailedResponse.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/events/StartShareRequestFailedResponse.java
new file mode 100755
index 0000000000000000000000000000000000000000..6d82ed0ad9cbb37e85a771d4c823fcfe9ddba9f9
--- /dev/null
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/events/StartShareRequestFailedResponse.java
@@ -0,0 +1,14 @@
+package org.bigbluebutton.app.screenshare.events;
+
+public class StartShareRequestFailedResponse implements IEvent {
+
+  public final String meetingId;
+  public final String userId;
+  public final String reason;
+
+  public StartShareRequestFailedResponse(String meetingId, String userId, String reason) {
+    this.meetingId = meetingId;
+    this.userId = userId;
+    this.reason = reason;
+  }
+}
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/events/StartShareRequestResponse.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/events/StartShareRequestResponse.java
new file mode 100755
index 0000000000000000000000000000000000000000..65fdaa2b5460fcf2fb8c2e7d8ecc1d950e8c3bc7
--- /dev/null
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/events/StartShareRequestResponse.java
@@ -0,0 +1,20 @@
+package org.bigbluebutton.app.screenshare.events;
+
+import org.bigbluebutton.app.screenshare.Error;
+
+public class StartShareRequestResponse implements IEvent {
+
+  public final String meetingId;
+  public final String userId;
+  public final String token;
+  public final String jnlp;
+  public final String streamId;
+  
+  public StartShareRequestResponse(String meetingId, String userId, String token, String jnlp, String streamId) {
+    this.meetingId = meetingId;
+    this.userId = userId;
+    this.token = token;
+    this.jnlp = jnlp;
+    this.streamId = streamId;
+  }
+}
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MeetingMessageHandler.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MeetingMessageHandler.java
index e4bf6fd309e761a3ea532cd608f57ebb587432ed..c6551880999c72e385bccd3e5cd2f2f3099e2579 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MeetingMessageHandler.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MeetingMessageHandler.java
@@ -6,7 +6,7 @@ import java.util.Map;
 import org.red5.logging.Red5LoggerFactory;
 import org.slf4j.Logger;
 import com.google.gson.Gson;
-
+import org.bigbluebutton.common.messages.MessagingConstants;
 
 public class MeetingMessageHandler implements MessageHandler {
 	private static Logger log = Red5LoggerFactory.getLogger(MeetingMessageHandler.class, "screenshare");
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageReceiver.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageReceiver.java
index a59df4c096472a43d3737d45c436b4282b286861..5747fe5406481ccc47fc9d621c2599ccfe3a142e 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageReceiver.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageReceiver.java
@@ -2,87 +2,107 @@ package org.bigbluebutton.app.screenshare.messaging.redis;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
+
+import org.bigbluebutton.common.messages.MessagingConstants;
 import org.red5.logging.Red5LoggerFactory;
 import org.slf4j.Logger;
+
 import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
 import redis.clients.jedis.JedisPubSub;
+import redis.clients.jedis.exceptions.JedisConnectionException;
 
 public class MessageReceiver {
-	private static Logger log = Red5LoggerFactory.getLogger(MessageReceiver.class, "bigbluebutton");
-	
-	private ReceivedMessageHandler handler;
-	
-	private JedisPool redisPool;
-	private volatile boolean receiveMessage = false;
-	
-	private final Executor msgReceiverExec = Executors.newSingleThreadExecutor();
-
-	public void stop() {
-		receiveMessage = false;
-	}
-	
-	public void start() {
-		log.info("Ready to receive messages from Redis pubsub.");
-		try {
-			receiveMessage = true;
-			final Jedis jedis = redisPool.getResource();
-			
-			Runnable messageReceiver = new Runnable() {
-			    public void run() {
-			    	if (receiveMessage) {
-			    		jedis.psubscribe(new PubSubListener(), MessagingConstants.TO_BBB_APPS_PATTERN); 
-			    	}
-			    }
-			};
-			msgReceiverExec.execute(messageReceiver);
-		} catch (Exception e) {
-			log.error("Error subscribing to channels: " + e.getMessage());
-		}			
-	}
-	
-	public void setRedisPool(JedisPool redisPool){
-		this.redisPool = redisPool;
-	}
-	
-	public void setMessageHandler(ReceivedMessageHandler handler) {
-		this.handler = handler;
-	}
-	
-	private class PubSubListener extends JedisPubSub {
-		
-		public PubSubListener() {
-			super();			
-		}
-
-		@Override
-		public void onMessage(String channel, String message) {
-			// Not used.
-		}
-
-		@Override
-		public void onPMessage(String pattern, String channel, String message) {
-			handler.handleMessage(pattern, channel, message);			
-		}
-
-		@Override
-		public void onPSubscribe(String pattern, int subscribedChannels) {
-			log.debug("Subscribed to the pattern: " + pattern);
-		}
-
-		@Override
-		public void onPUnsubscribe(String pattern, int subscribedChannels) {
-			// Not used.
-		}
-
-		@Override
-		public void onSubscribe(String channel, int subscribedChannels) {
-			// Not used.
-		}
-
-		@Override
-		public void onUnsubscribe(String channel, int subscribedChannels) {
-			// Not used.
-		}		
-	}
+    private static Logger log = Red5LoggerFactory.getLogger(MessageReceiver.class, "screenshare");
+
+    private ReceivedMessageHandler handler;
+
+    private Jedis jedis;
+    private volatile boolean receiveMessage = false;
+
+    private final Executor msgReceiverExec = Executors.newSingleThreadExecutor();
+
+    private String host;
+    private int port;
+
+    public void stop() {
+        receiveMessage = false;
+    }
+
+    public void start() {
+        log.info("Ready to receive messages from Redis pubsub.");
+        try {
+            receiveMessage = true;
+            jedis = new Jedis(host, port);
+            // Set the name of this client to be able to distinguish when doing
+            // CLIENT LIST on redis-cli
+            jedis.clientSetname("bbb-screenshare");
+
+            Runnable messageReceiver = new Runnable() {
+                public void run() {
+                    if (receiveMessage) {
+                        try {
+                            jedis.psubscribe(new PubSubListener(),
+                                    MessagingConstants.FROM_BBB_APPS_PATTERN);
+                        } catch(JedisConnectionException ex) {
+                            log.warn("Exception on Jedis connection. Resubscribing to pubsub.");
+                            start();
+                        }
+
+                    }
+                }
+            };
+            msgReceiverExec.execute(messageReceiver);
+        } catch (Exception e) {
+            log.error("Error subscribing to channels: " + e.getMessage());
+        }
+    }
+
+    public void setHost(String host){
+        this.host = host;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public void setMessageHandler(ReceivedMessageHandler handler) {
+        this.handler = handler;
+    }
+
+    private class PubSubListener extends JedisPubSub {
+
+        public PubSubListener() {
+            super();
+        }
+
+        @Override
+        public void onMessage(String channel, String message) {
+            // Not used.
+        }
+
+        @Override
+        public void onPMessage(String pattern, String channel, String message) {
+            handler.handleMessage(pattern, channel, message);
+        }
+
+        @Override
+        public void onPSubscribe(String pattern, int subscribedChannels) {
+            log.debug("Subscribed to the pattern: " + pattern);
+        }
+
+        @Override
+        public void onPUnsubscribe(String pattern, int subscribedChannels) {
+            // Not used.
+        }
+
+        @Override
+        public void onSubscribe(String channel, int subscribedChannels) {
+            // Not used.
+        }
+
+        @Override
+        public void onUnsubscribe(String channel, int subscribedChannels) {
+            // Not used.
+        }
+    }
 }
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageSender.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageSender.java
index 18067a0a986a34ae5b7440e0c90decafeb8ef410..182ab1dac605fa0b6cdc2e7216ab476de0afecdc 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageSender.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessageSender.java
@@ -4,71 +4,99 @@ import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
 import org.red5.logging.Red5LoggerFactory;
 import org.slf4j.Logger;
+
 import redis.clients.jedis.Jedis;
 import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.Protocol;
 
 public class MessageSender {
-	private static Logger log = Red5LoggerFactory.getLogger(MessageSender.class, "bigbluebutton");
-	
-	private JedisPool redisPool;
-	private volatile boolean sendMessage = false;
-	
-	private final Executor msgSenderExec = Executors.newSingleThreadExecutor();
-	private final Executor runExec = Executors.newSingleThreadExecutor();
-	private BlockingQueue<MessageToSend> messages = new LinkedBlockingQueue<MessageToSend>();
-	
-	public void stop() {
-		sendMessage = false;
-	}
-	
-	public void start() {	
-		log.info("Redis message publisher starting!");
-		try {
-			sendMessage = true;
-			
-			Runnable messageSender = new Runnable() {
-			    public void run() {
-			    	while (sendMessage) {
-				    	try {
-							MessageToSend msg = messages.take();
-							publish(msg.getChannel(), msg.getMessage());
-						} catch (InterruptedException e) {
-							log.warn("Failed to get message from queue.");
-						}    			    		
-			    	}
-			    }
-			};
-			msgSenderExec.execute(messageSender);
-		} catch (Exception e) {
-			log.error("Error subscribing to channels: " + e.getMessage());
-		}			
-	}
-	
-	public void send(String channel, String message) {
-		MessageToSend msg = new MessageToSend(channel, message);
-		messages.add(msg);
-	}
-	
-	private void publish(final String channel, final String message) {
-		Runnable task = new Runnable() {
-	    public void run() {
-	  		Jedis jedis = redisPool.getResource();
-	  		try {
-	  			jedis.publish(channel, message);
-	  		} catch(Exception e){
-	  			log.warn("Cannot publish the message to redis", e);
-	  		} finally {
-	  			redisPool.returnResource(jedis);
-	  		}	    	
-	    }
-		};
-		
-		runExec.execute(task);
-	}
-	
-	public void setRedisPool(JedisPool redisPool){
-		this.redisPool = redisPool;
-	}
+    private static Logger log = Red5LoggerFactory.getLogger(MessageSender.class, "bigbluebutton");
+
+    private volatile boolean sendMessage = false;
+    private final Executor msgSenderExec = Executors.newSingleThreadExecutor();
+    private final Executor runExec = Executors.newSingleThreadExecutor();
+    private BlockingQueue<MessageToSend> messages = new LinkedBlockingQueue<MessageToSend>();
+
+    private JedisPool redisPool;
+    private String host;
+    private int port;
+
+    public void stop() {
+        sendMessage = false;
+        redisPool.destroy();
+    }
+
+    public void start() {
+        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
+        config.setMaxTotal(32);
+        config.setMaxIdle(8);
+        config.setMinIdle(1);
+        config.setTestOnBorrow(true);
+        config.setTestOnReturn(true);
+        config.setTestWhileIdle(true);
+        config.setNumTestsPerEvictionRun(12);
+        config.setMaxWaitMillis(5000);
+        config.setTimeBetweenEvictionRunsMillis(60000);
+        config.setBlockWhenExhausted(true);
+
+        // Set the name of this client to be able to distinguish when doing
+        // CLIENT LIST on redis-cli
+        redisPool = new JedisPool(config, host, port, Protocol.DEFAULT_TIMEOUT, null,
+                Protocol.DEFAULT_DATABASE, "BbbRed5AppsPub");
+
+        log.info("Redis message publisher starting!");
+        try {
+            sendMessage = true;
+
+            Runnable messageSender = new Runnable() {
+                public void run() {
+                    while (sendMessage) {
+                        try {
+                            MessageToSend msg = messages.take();
+                            publish(msg.getChannel(), msg.getMessage());
+                        } catch (InterruptedException e) {
+                            log.warn("Failed to get message from queue.");
+                        }
+                    }
+                }
+            };
+            msgSenderExec.execute(messageSender);
+        } catch (Exception e) {
+            log.error("Error subscribing to channels: " + e.getMessage());
+        }
+    }
+
+    public void send(String channel, String message) {
+        MessageToSend msg = new MessageToSend(channel, message);
+        messages.add(msg);
+    }
+
+    private void publish(final String channel, final String message) {
+        Runnable task = new Runnable() {
+            public void run() {
+                Jedis jedis = redisPool.getResource();
+                try {
+                    jedis.publish(channel, message);
+                } catch(Exception e){
+                    log.warn("Cannot publish the message to redis", e);
+                } finally {
+                    jedis.close();
+                }
+            }
+        };
+
+        runExec.execute(task);
+    }
+
+    public void setHost(String host){
+        this.host = host;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
 }
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessagingConstants.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessagingConstants.java
deleted file mode 100755
index 0a787e84d3788d7d562b198694078f545ce84e74..0000000000000000000000000000000000000000
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/MessagingConstants.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
-* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-* 
-* Copyright (c) 2014 BigBlueButton Inc. and by respective authors (see below).
-*
-* This program is free software; you can redistribute it and/or modify it under the
-* terms of the GNU Lesser General Public License as published by the Free Software
-* Foundation; either version 3.0 of the License, or (at your option) any later
-* version.
-* 
-* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License along
-* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-*
-*/
-package org.bigbluebutton.app.screenshare.messaging.redis;
-
-public class MessagingConstants {
-	
-	public static final String FROM_BBB_APPS_CHANNEL = "bigbluebutton:from-bbb-apps";
-	public static final String FROM_BBB_APPS_PATTERN = FROM_BBB_APPS_CHANNEL + ":*";
-	public static final String FROM_SYSTEM_CHANNEL = FROM_BBB_APPS_CHANNEL + ":system";
-	public static final String FROM_MEETING_CHANNEL = FROM_BBB_APPS_CHANNEL + ":meeting";
-
-	public static final String TO_BBB_APPS_CHANNEL = "bigbluebutton:to-bbb-apps";	
-	public static final String TO_BBB_APPS_PATTERN = TO_BBB_APPS_CHANNEL + ":*";
-	public static final String TO_MEETING_CHANNEL = TO_BBB_APPS_CHANNEL + ":meeting";	
-	public static final String TO_SYSTEM_CHANNEL = TO_BBB_APPS_CHANNEL + ":system";
-
-	public static final String DESTROY_MEETING_REQUEST_EVENT = "DestroyMeetingRequestEvent";
-	public static final String CREATE_MEETING_REQUEST_EVENT = "CreateMeetingRequestEvent";	
-	public static final String END_MEETING_REQUEST_EVENT = "EndMeetingRequestEvent";
-	public static final String MEETING_STARTED_EVENT = "meeting_created_message";
-	public static final String MEETING_ENDED_EVENT = "meeting_ended_event";
-	public static final String MEETING_DESTROYED_EVENT = "meeting_destroyed_event";
-
-}
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/RedisPubSubMessageHandler.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/RedisPubSubMessageHandler.java
new file mode 100755
index 0000000000000000000000000000000000000000..9d64989664e73431bd1b54afc527db1e8163cc99
--- /dev/null
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/messaging/redis/RedisPubSubMessageHandler.java
@@ -0,0 +1,46 @@
+package org.bigbluebutton.app.screenshare.messaging.redis;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.bigbluebutton.app.screenshare.red5.Red5AppHandler;
+import org.bigbluebutton.common.messages.MeetingDestroyedMessage;
+import org.bigbluebutton.common.messages.MeetingCreatedMessage;
+import org.bigbluebutton.common.messages.MessagingConstants;
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
+
+public class RedisPubSubMessageHandler implements MessageHandler {
+    private static Logger log = Red5LoggerFactory.getLogger(RedisPubSubMessageHandler.class, "screenshare");
+    private Red5AppHandler handler;
+
+    @Override
+    public void handleMessage(String pattern, String channel, String message) {
+        if (channel.equalsIgnoreCase(MessagingConstants.FROM_MEETING_CHANNEL)) {
+            JsonParser parser = new JsonParser();
+            JsonObject obj = (JsonObject) parser.parse(message);
+            if (obj.has("header") && obj.has("payload")) {
+                JsonObject header = (JsonObject) obj.get("header");
+                if (header.has("name")) {
+                    String messageName = header.get("name").getAsString();
+
+                    if (MeetingDestroyedMessage.NAME.equals(messageName)) {
+                        MeetingDestroyedMessage msg = MeetingDestroyedMessage.fromJson(message);
+                        handler.meetingHasEnded(msg.meetingId);
+
+                    } else if (MeetingCreatedMessage.MEETING_CREATED.equals(messageName)) {
+                        MeetingCreatedMessage msg = MeetingCreatedMessage.fromJson(message);
+                        handler.meetingCreated(msg.meetingId);
+
+                    }
+                }
+            }
+        }
+
+
+    }
+
+    public void setAppHandler(Red5AppHandler handler) {
+        this.handler = handler;
+  }
+
+}
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 12f811f039ce2c3c4f907791de82e4917e444e92..54b75a028090c50b1bb5fb51bb0802f8c11c05ae 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
@@ -65,7 +65,7 @@ public class ConnectionInvokerService {
           ClientMessage message;
           try {
             message = messages.take();
-            sendMessageToClient(message);	
+            sendMessageToClient(message);
           } catch (InterruptedException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/EventListenerImp.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/EventListenerImp.java
index d42bdd32d897204c03e9e6fcabd0b57c88650a8f..6425eff75c7557cb05fb78158a05e2d5576e580a 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/EventListenerImp.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/EventListenerImp.java
@@ -2,14 +2,7 @@ package org.bigbluebutton.app.screenshare.red5;
 
 import java.util.HashMap;
 import java.util.Map;
-
-import org.bigbluebutton.app.screenshare.events.IEvent;
-import org.bigbluebutton.app.screenshare.events.IEventListener;
-import org.bigbluebutton.app.screenshare.events.ShareStartedEvent;
-import org.bigbluebutton.app.screenshare.events.ShareStoppedEvent;
-import org.bigbluebutton.app.screenshare.events.StreamStartedEvent;
-import org.bigbluebutton.app.screenshare.events.StreamStoppedEvent;
-
+import org.bigbluebutton.app.screenshare.events.*;
 import com.google.gson.Gson;
 import org.red5.logging.Red5LoggerFactory;
 import org.slf4j.Logger;
@@ -28,10 +21,86 @@ public class EventListenerImp implements IEventListener {
       sendStreamStartedEvent((StreamStartedEvent) event);
     } else if (event instanceof StreamStoppedEvent) {
       sendStreamStoppedEvent((StreamStoppedEvent) event);
+    } else if (event instanceof StartShareRequestResponse) {
+      sendStartShareRequestResponse((StartShareRequestResponse) event);
+    } else if (event instanceof StartShareRequestFailedResponse) {
+      sendStartShareRequestFailedResponse((StartShareRequestFailedResponse) event);
+    }  else if (event instanceof IsScreenSharingResponse) {
+        sendIsScreenSharingResponse((IsScreenSharingResponse) event);
     }
-    
   }
-  
+
+  private void sendIsScreenSharingResponse(IsScreenSharingResponse event) {
+      Map<String, Object> data = new HashMap<String, Object>();
+      data.put("sharing", event.info.sharing);
+
+      if (event.info.sharing) {
+          data.put("streamId", event.info.streamId);
+          data.put("width", event.info.width);
+          data.put("height", event.info.height);
+          data.put("url", event.info.url);
+      }
+
+      Map<String, Object> message = new HashMap<String, Object>();
+      Gson gson = new Gson();
+      message.put("msg", gson.toJson(data));
+
+      log.info("Sending isSharingScreenRequestResponse to client, meetingId=" + event.meetingId + " userid=" + event.userId);
+      DirectClientMessage msg = new DirectClientMessage(event.meetingId, event.userId, "isSharingScreenRequestResponse", message);
+      sender.sendMessage(msg);
+  }
+
+  private void  sendStartShareRequestFailedResponse(StartShareRequestFailedResponse event) {
+    Map<String, Object> data = new HashMap<String, Object>();
+
+    data.put("reason", event.reason);
+
+    Map<String, Object> message = new HashMap<String, Object>();
+    Gson gson = new Gson();
+    message.put("msg", gson.toJson(data));
+
+    DirectClientMessage msg = new DirectClientMessage(event.meetingId, event.userId, "startShareRequestRejectedResponse", message);
+    sender.sendMessage(msg);
+
+    Map<String, Object> logData = new HashMap<String, Object>();
+    logData.put("meetingId", event.meetingId);
+    logData.put("userId", event.userId);
+    logData.put("reason", event.reason);
+
+    Gson gson2 = new Gson();
+    String logStr =  gson2.toJson(logData);
+
+    log.info("Start ScreenShare request rejected response: data={}", logStr);
+  }
+
+  private void  sendStartShareRequestResponse(StartShareRequestResponse event) {
+    Map<String, Object> data = new HashMap<String, Object>();
+
+    data.put("authToken", event.token);
+    data.put("jnlp", event.jnlp);
+    data.put("streamId", event.streamId);
+
+    Map<String, Object> message = new HashMap<String, Object>();
+    Gson gson = new Gson();
+    message.put("msg", gson.toJson(data));
+
+    DirectClientMessage msg = new DirectClientMessage(event.meetingId, event.userId, "startShareRequestResponse", message);
+    sender.sendMessage(msg);
+
+    Map<String, Object> logData = new HashMap<String, Object>();
+    logData.put("meetingId", event.meetingId);
+    logData.put("userId", event.userId);
+
+    logData.put("authToken", event.token);
+    logData.put("jnlp", event.jnlp);
+
+
+    Gson gson2 = new Gson();
+    String logStr =  gson2.toJson(logData);
+
+    log.info("Start ScreenShare request response: data={}", logStr);
+  }
+
   private void sendShareStartedEvent(ShareStartedEvent event) {
     Map<String, Object> data = new HashMap<String, Object>();
     data.put("meetingId", event.meetingId);
@@ -131,4 +200,7 @@ public class EventListenerImp implements IEventListener {
     this.sender = sender;
   }
 
+
+
+
 }
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppHandler.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppHandler.java
index b5c726da353ce60ab834a478c7e60faaca7182ca..245b00bbbedbb76dfccdd8209ad2c135ca3dc814 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppHandler.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppHandler.java
@@ -5,8 +5,7 @@ import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.bigbluebutton.app.screenshare.IScreenShareApplication;
-import org.bigbluebutton.app.screenshare.IsScreenSharingResponse;
-import org.bigbluebutton.app.screenshare.StartShareRequestResponse;
+import org.bigbluebutton.app.screenshare.events.IsScreenSharingResponse;
 import org.red5.logging.Red5LoggerFactory;
 import org.slf4j.Logger;
 import com.google.gson.Gson;
@@ -19,81 +18,30 @@ public class Red5AppHandler {
   
   private final Pattern STREAM_ID_PATTERN = Pattern.compile("(.*)-(.*)-(.*)$");
 
+  public void meetingHasEnded(String meetingId) {
+    app.meetingHasEnded(meetingId);
+  }
+
+  public void meetingCreated(String meetingId) {
+    app.meetingCreated(meetingId);
+  }
+
   public void userConnected(String meetingId, String userId) {
     app.userConnected(meetingId, userId);
   }
 
   public void isScreenSharing(String meetingId, String userId) {
-    IsScreenSharingResponse resp = app.isScreenSharing(meetingId);
-    
-    Map<String, Object> data = new HashMap<String, Object>();
-    data.put("sharing", resp.info.sharing);
-    
-    if (resp.info.sharing) {
-      data.put("streamId", resp.info.streamId);
-      data.put("width", resp.info.width);
-      data.put("height", resp.info.height);     
-      data.put("url", resp.info.url);
-    }
-    
-    Map<String, Object> message = new HashMap<String, Object>(); 
-    Gson gson = new Gson();
-    message.put("msg", gson.toJson(data));
-
-    log.info("Sending isSharingScreenRequestResponse to client, meetingId=" + meetingId + " userid=" + userId);
-    DirectClientMessage msg = new DirectClientMessage(meetingId, userId, "isSharingScreenRequestResponse", message);
-    sender.sendMessage(msg);    
+    app.isScreenSharing(meetingId, userId);
   }
   
-  public void startShareRequest(String meetingId, String userId, Boolean record) {
-    StartShareRequestResponse resp = app.startShareRequest(meetingId, userId, record);
-    
-    Map<String, Object> data = new HashMap<String, Object>();
-    
-    if (resp.error != null) {
-      data.put("error", resp.error.reason);
-    } else {
-      data.put("authToken", resp.token);
-      data.put("jnlp", resp.jnlp);
-      data.put("streamId", resp.streamId);
-    }
-    
-    Map<String, Object> message = new HashMap<String, Object>(); 
-    Gson gson = new Gson();
-    message.put("msg", gson.toJson(data));
-
-    DirectClientMessage msg = new DirectClientMessage(meetingId, userId, "startShareRequestResponse", message);
-    sender.sendMessage(msg);
-
-    Map<String, Object> logData = new HashMap<String, Object>();
-    logData.put("meetingId", meetingId);
-    logData.put("userId", userId);
-
-    if (resp.error != null) {
-      logData.put("error", resp.error.reason);
-    } else {
-      logData.put("authToken", resp.token);
-      logData.put("jnlp", resp.jnlp);
-    }
-
-    Gson gson2 = new Gson();
-    String logStr =  gson2.toJson(logData);
-
-    log.info("Start ScreenShare request response: data={}", logStr);
+  public void startShareRequest(String meetingId, String userId, Boolean allowed) {
+    app.startShareRequest(meetingId, userId, allowed);
   }
 
   public void restartShareRequest(String meetingId, String userId) {
 
     app.restartShareRequest(meetingId, userId);
 
-    Map<String, Object> logData = new HashMap<String, Object>();
-    logData.put("meetingId", meetingId);
-    logData.put("userId", userId);
-
-    Gson gson2 = new Gson();
-    String logStr =  gson2.toJson(logData);
-
-    log.info("Restart ScreenShare message: data={}", logStr);
   }
 
   public void pauseShareRequest(String meetingId, String userId, String streamId) {
@@ -101,54 +49,13 @@ public class Red5AppHandler {
     if (matcher.matches()) {
       app.pauseShareRequest(meetingId, userId, streamId);
     }
-
-    Map<String, Object> data = new HashMap<String, Object>();
-    data.put("meetingId", meetingId);
-    data.put("streamId", streamId);
-    data.put("userId", userId);
-
-    Map<String, Object> message = new HashMap<String, Object>();
-    Gson gson = new Gson();
-    message.put("msg", gson.toJson(data));
-
-    BroadcastClientMessage msg = new BroadcastClientMessage(meetingId, "pauseScreenSharingEvent", message);
-    sender.sendMessage(msg);
-
-    Map<String, Object> logData = new HashMap<String, Object>();
-    logData.put("meetingId", meetingId);
-    logData.put("streamId", streamId);
-
-    Gson gson2 = new Gson();
-    String logStr =  gson2.toJson(logData);
-
-    log.info("Stop viewing ScreenShare broadcast message: data={}", logStr);
   }
 
   public void stopShareRequest(String meetingId, String streamId) {
     Matcher matcher = STREAM_ID_PATTERN.matcher(streamId);
     if (matcher.matches()) {            
         app.stopShareRequest(meetingId, streamId);
-    }   
-    
-    Map<String, Object> data = new HashMap<String, Object>();
-    data.put("meetingId", meetingId);
-    data.put("streamId", streamId);
-    
-    Map<String, Object> message = new HashMap<String, Object>(); 
-    Gson gson = new Gson();
-    message.put("msg", gson.toJson(data));
-
-    BroadcastClientMessage msg = new BroadcastClientMessage(meetingId, "stopViewingStream", message);
-    sender.sendMessage(msg);
-
-    Map<String, Object> logData = new HashMap<String, Object>();
-    logData.put("meetingId", meetingId);
-    logData.put("streamId", streamId);
-
-    Gson gson2 = new Gson();
-    String logStr =  gson2.toJson(logData);
-
-    log.info("Stop viewing ScreenShare broadcast message: data={}", logStr);
+    }
   }
     
   public void setApplication(IScreenShareApplication app) {
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 352ef84af8d72edd5035e8ccdf52933262806cc5..2697a37c0cb94cee9d784af20df0ca2db3d2047b 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
@@ -3,7 +3,12 @@ package org.bigbluebutton.app.screenshare.red5;
 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;
@@ -15,7 +20,8 @@ import com.google.gson.Gson;
 public class Red5AppService {
   private static Logger log = Red5LoggerFactory.getLogger(Red5AppService.class, "screenshare");
   
-  private Red5AppHandler handler; 
+  private Red5AppHandler handler;
+  private MessageSender red5RedisSender;
 
   /**
    * Called from the client to pass us the userId.
@@ -97,12 +103,12 @@ public class Red5AppService {
   }
 
   public void startShareRequest(Map<String, Object> msg) {
-	Boolean record = (Boolean) msg.get("record");
+    Boolean record = (Boolean) msg.get("record");
     String meetingId = Red5.getConnectionLocal().getScope().getName();
     log.debug("Received startShareRequest for meeting=[{}]", meetingId);
     String userId = (String) Red5.getConnectionLocal().getAttribute("USERID");
 
-    handler.startShareRequest(meetingId, userId, record);
+    handler.startShareRequest(meetingId, userId, record); //TODO REMOVE
   }
 
   public void stopShareRequest(Map<String, Object> msg) {
@@ -113,8 +119,15 @@ public class Red5AppService {
     handler.stopShareRequest(meetingId, streamId);
   }
 
+  private Long genTimestamp() {
+    return TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
+  }
 
   public void setAppHandler(Red5AppHandler handler) {
     this.handler = handler;
   }
+
+  public void setRed5RedisSender(MessageSender red5RedisSender) {
+      this.red5RedisSender = red5RedisSender;
+  }
 }
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/ScreenShareApplication.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/ScreenShareApplication.scala
index 623945609d5b4c4852f7d62c9000a7b0e1e26b27..c7355d7d7aebf6e9b706ff682d9ec9eb58ba886e 100755
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/ScreenShareApplication.scala
+++ b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/ScreenShareApplication.scala
@@ -19,12 +19,13 @@
 package org.bigbluebutton.app.screenshare
 
 import akka.util.Timeout
-import org.bigbluebutton.app.screenshare.events.IEventsMessageBus
+import org.bigbluebutton.app.screenshare.events.{IEventsMessageBus, IsScreenSharingResponse, StartShareRequestResponse}
 import org.bigbluebutton.app.screenshare.server.sessions.ScreenshareManager
 import org.bigbluebutton.app.screenshare.server.sessions.messages._
 import org.bigbluebutton.app.screenshare.server.util.LogHelper
 import akka.actor.ActorSystem
 import akka.pattern.ask
+
 import scala.concurrent.Await
 import scala.concurrent.duration._
 
@@ -39,6 +40,24 @@ class ScreenShareApplication(val bus: IEventsMessageBus, val jnlpFile: String,
 
   logger.info("Creating a new ScreenShareApplication")
 
+  def meetingHasEnded(meetingId: String) {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Received meetingHasEnded on meeting=" + meetingId + "]")
+    }
+
+    screenshareManager ! new MeetingHasEnded(meetingId)
+
+  }
+
+  def meetingCreated(meetingId: String) {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Received meetingCreated on meeting=" + meetingId + "]")
+    }
+
+    screenshareManager ! new MeetingCreated(meetingId)
+
+  }
+
   def userConnected(meetingId: String, userId: String) {
     if (logger.isDebugEnabled()) {
       logger.debug("Received user disconnected on meeting=" + meetingId
@@ -55,16 +74,12 @@ class ScreenShareApplication(val bus: IEventsMessageBus, val jnlpFile: String,
     screenshareManager ! new UserDisconnected(meetingId, userId)
   }
 
-  def isScreenSharing(meetingId: String):IsScreenSharingResponse = {
+  def isScreenSharing(meetingId: String, userId: String) {
     if (logger.isDebugEnabled()) {
       logger.debug("Received is screen sharing on meeting=" + meetingId + "]")
     }
-    implicit val timeout = Timeout(3 seconds)
-    val future = screenshareManager ? IsScreenSharing(meetingId)
-    val reply = Await.result(future, timeout.duration).asInstanceOf[IsScreenSharingReply]
 
-    val info = new StreamInfo(reply.sharing, reply.streamId, reply.width, reply.height, reply.url)
-    new IsScreenSharingResponse(info, null)
+    screenshareManager ! IsScreenSharing(meetingId, userId)
   }
   
   def getScreenShareInfo(meetingId: String, token: String):ScreenShareInfoResponse = {
@@ -93,16 +108,12 @@ class ScreenShareApplication(val bus: IEventsMessageBus, val jnlpFile: String,
     record
   }
 
-  def startShareRequest(meetingId: String, userId: String, record: java.lang.Boolean): StartShareRequestResponse = {
+  def startShareRequest(meetingId: String, userId: String, record: java.lang.Boolean) {
     if (logger.isDebugEnabled()) {
       logger.debug("Received start share request on meeting=" + meetingId + "for user=" + userId + "]")
     }
-    implicit val timeout = Timeout(3 seconds)
-    val future = screenshareManager ? StartShareRequestMessage(meetingId, userId, record)
-    val reply = Await.result(future, timeout.duration).asInstanceOf[StartShareRequestReplyMessage]
 
-    val response = new StartShareRequestResponse(reply.token, jnlpFile, reply.streamId, null)
-    response
+    screenshareManager ! StartShareRequestMessage(meetingId, userId, jnlpFile, record)
   }
 
   def restartShareRequest(meetingId: String, userId: String) {
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/Screenshare.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/Screenshare.scala
index 748a76613ede473786faedb846cfe5e89a26922d..a21cab9346567ea908524be7bdade15eb829e276 100755
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/Screenshare.scala
+++ b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/Screenshare.scala
@@ -19,16 +19,14 @@
 package org.bigbluebutton.app.screenshare.server.sessions
 
 import akka.actor.{Actor, ActorLogging, Props}
-import org.bigbluebutton.app.screenshare.server.sessions.Session.KeepAliveTimeout
+import org.bigbluebutton.app.screenshare.StreamInfo
 import org.bigbluebutton.app.screenshare.server.sessions.ScreenshareManager.MeetingHasEnded
 
 import scala.collection.mutable.HashMap
-import org.bigbluebutton.app.screenshare.events.IEventsMessageBus
-import org.bigbluebutton.app.screenshare.server.util._
+import org.bigbluebutton.app.screenshare.events.{IEventsMessageBus, IsScreenSharingResponse, StartShareRequestResponse}
 import org.bigbluebutton.app.screenshare.server.sessions.messages._
 
 import scala.collection.immutable.StringOps
-import scala.concurrent.duration._
 
 object Screenshare {
   def props(screenshareSessionManager: ScreenshareManager, bus: IEventsMessageBus, meetingId:String): Props =
@@ -42,8 +40,6 @@ class Screenshare(val sessionManager: ScreenshareManager,
   log.info("Creating a new Screenshare")
   private val sessions = new HashMap[String, ActiveSession]
 
-  private var lastHasSessionCheck:Long = TimeUtil.getCurrentMonoTime()
-  
   private var activeSession:Option[ActiveSession] = None
 
   private val START = "START"
@@ -60,17 +56,10 @@ class Screenshare(val sessionManager: ScreenshareManager,
 
   private var sessionToken = ""
 
-  private val IS_MEETING_RUNNING = "IsMeetingRunning"
-
   private var currentStreamId:Option[String] = None
   private var currentPresenterId:Option[String] = None
   private var record:Boolean = false
 
-  implicit def executionContext = sessionManager.actorSystem.dispatcher
-
-  def scheduleIsMeetingRunningCheck() {
-    sessionManager.actorSystem.scheduler.scheduleOnce(60.seconds, self, IS_MEETING_RUNNING)
-  }
 
   def receive = {
     case msg: RestartShareRequestMessage => handleRestartShareRequestMessage(msg)
@@ -88,8 +77,7 @@ class Screenshare(val sessionManager: ScreenshareManager,
     case msg: UserDisconnected => handleUserDisconnected(msg)
     case msg: UserConnected => handleUserConnected(msg)
     case msg: ScreenShareInfoRequest => handleScreenShareInfoRequest(msg)
-    case IS_MEETING_RUNNING => handleIsMeetingRunning()
-    case msg: KeepAliveTimeout => handleKeepAliveTimeout(msg)
+    case msg: MeetingHasEnded             => handleMeetingHasEnded(msg)
     case m: Any => log.warning("Session: Unknown message [{}]", m)
   }
 
@@ -101,6 +89,18 @@ class Screenshare(val sessionManager: ScreenshareManager,
     sessions.values find (su => su.token == token)
   }
 
+  private def handleMeetingHasEnded(msg: MeetingHasEnded) {
+    if (log.isDebugEnabled) {
+      log.debug("Received MeetingHasEnded for meetingId=[" + msg.meetingId + "]")
+    }
+
+    activeSession foreach { session =>
+      context.stop(session.actorRef)
+    }
+
+    context.stop(self)
+  }
+
   private def handleUserDisconnected(msg: UserDisconnected) {
     if (log.isDebugEnabled) {
       log.debug("Received UserDisconnected for meetingId=[" + msg.meetingId + "] userId=[" + msg.userId + "]")
@@ -118,7 +118,6 @@ class Screenshare(val sessionManager: ScreenshareManager,
           currentStreamId foreach { curStreamId =>
             handleStopShareRequestMessage(new StopShareRequestMessage(meetingId, curStreamId))
           }
-
         }
       }
     }
@@ -152,7 +151,8 @@ class Screenshare(val sessionManager: ScreenshareManager,
     }
 
     if (activeSession.isEmpty) {
-      sender ! new IsScreenSharingReply(false, "none", 0, 0, "none")
+      val info = new StreamInfo(false, "", 0, 0, "")
+      bus.send(new IsScreenSharingResponse(meetingId, msg.userId, info))
     } else {
       activeSession foreach { session =>
         session.actorRef forward msg
@@ -276,7 +276,6 @@ class Screenshare(val sessionManager: ScreenshareManager,
     }
   }
 
-
   private def handlePauseShareRequestMessage(msg: PauseShareRequestMessage) {
     if (log.isDebugEnabled) {
       log.debug("Received PauseShareRequestMessage for streamId=[" + msg.streamId + "]")
@@ -289,8 +288,7 @@ class Screenshare(val sessionManager: ScreenshareManager,
         session.actorRef ! msg
 
       case None =>
-        log.info("Stop share request on a non-existing session=[" + msg.streamId + "]")
-
+        log.info("PauseShareRequestMessage on a non-existing session=[" + msg.streamId + "]")
     }
   }
 
@@ -347,7 +345,8 @@ class Screenshare(val sessionManager: ScreenshareManager,
     status = START
 
     session.actorRef ! msg
-    sender ! new StartShareRequestReplyMessage(token, streamId)
+
+    bus.send(new StartShareRequestResponse(meetingId, msg.userId, token, msg.jnlp, streamId))
   }
 
   private def handleGetSharingStatus(msg: GetSharingStatus) {
@@ -367,29 +366,4 @@ class Screenshare(val sessionManager: ScreenshareManager,
       }
     }
   }
-
-  private def handleIsMeetingRunning() {
-    // If not sessions in the last 5 minutes, then assume meeting has ended.
-    if (sessions.isEmpty) {
-      if (TimeUtil.getCurrentMonoTime - lastHasSessionCheck > 300000) {
-        context.parent ! MeetingHasEnded(meetingId)
-      } else {
-        scheduleIsMeetingRunningCheck()
-      }
-    } else {
-      lastHasSessionCheck = TimeUtil.getCurrentMonoTime()
-      scheduleIsMeetingRunningCheck()
-    } 
-  }
-
-  private def handleKeepAliveTimeout(msg: KeepAliveTimeout) {
-    sessions.remove(msg.streamId) foreach { s =>
-      if (activeSession != None) {
-        activeSession foreach { as =>
-          if (as.streamId == s.streamId) activeSession = None
-        }
-      }
-    }
-  }
-
 }
\ No newline at end of file
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/ScreenshareManager.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/ScreenshareManager.scala
index 27f57f37369e576b636358182a618680e8508bea..35c5f4229918e8e8b3d7fb148e89f938d5fb9bd8 100755
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/ScreenshareManager.scala
+++ b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/ScreenshareManager.scala
@@ -19,13 +19,16 @@
 package org.bigbluebutton.app.screenshare.server.sessions
 
 import akka.pattern.ask
+
 import scala.concurrent.duration._
-import akka.actor.{ActorSystem, Actor, Props, ActorLogging}
+import akka.actor.{Actor, ActorLogging, ActorSystem, Props}
 import akka.util.Timeout
+import org.bigbluebutton.app.screenshare.StreamInfo
 import org.bigbluebutton.app.screenshare.server.sessions.Session.StopSession
 import org.bigbluebutton.app.screenshare.server.sessions.ScreenshareManager.MeetingHasEnded
+
 import scala.collection.mutable.HashMap
-import org.bigbluebutton.app.screenshare.events.IEventsMessageBus
+import org.bigbluebutton.app.screenshare.events.{IEventsMessageBus, IsScreenSharingResponse, StartShareRequestFailedResponse}
 import org.bigbluebutton.app.screenshare.server.sessions.messages._
 
 import scala.concurrent.Await
@@ -63,6 +66,8 @@ class ScreenshareManager(val aSystem: ActorSystem, val bus: IEventsMessageBus)
     case msg: UserDisconnected            => handleUserDisconnected(msg)
     case msg: UserConnected               => handleUserConnected(msg)
     case msg: MeetingHasEnded             => handleMeetingHasEnded(msg)
+    case msg: MeetingCreated              => handleMeetingCreated(msg)
+
 
     case msg: Any => log.warning("Unknown message " + msg)
   }
@@ -101,7 +106,8 @@ class ScreenshareManager(val aSystem: ActorSystem, val bus: IEventsMessageBus)
     }
 
     if (screenshares.get(msg.meetingId).isEmpty) {
-      sender ! new IsScreenSharingReply(false, "none", 0, 0, "none")
+      val info = new StreamInfo(false, "", 0, 0, "")
+      bus.send(new IsScreenSharingResponse(msg.meetingId, msg.userId, info))
     } else {
       screenshares.get(msg.meetingId) foreach { screenshare =>
         screenshare.actorRef forward msg
@@ -111,9 +117,34 @@ class ScreenshareManager(val aSystem: ActorSystem, val bus: IEventsMessageBus)
 
   private def handleMeetingHasEnded(msg: MeetingHasEnded) {
     log.info("Removing meeting [" + msg.meetingId + "]")
+
+    screenshares.get(msg.meetingId) foreach { screenshare =>
+      screenshare.actorRef forward msg
+    }
+
     screenshares -= msg.meetingId
   }
 
+  private def handleMeetingCreated(msg: MeetingCreated) {
+    log.info("Creating meeting [" + msg.meetingId + "]")
+
+    screenshares.get(msg.meetingId) match {
+      case None => {
+        if (log.isDebugEnabled) {
+          log.debug("Creating screenshare=[" + msg.meetingId + "]")
+        }
+        val activeScreenshare = ActiveScreenshare(this, bus, msg.meetingId)
+        screenshares += msg.meetingId -> activeScreenshare
+
+      }
+      case Some(screenshare) => {
+        if (log.isDebugEnabled) {
+          log.debug("Screenshare already exists. screenshare=[" + msg.meetingId + "]")
+        }
+      }
+    }
+  }
+
   private def handleScreenShareInfoRequest(msg: ScreenShareInfoRequest) {
     if (log.isDebugEnabled) {
       log.debug("Received ScreenShareInfoRequest message for meetingId=[" + msg.meetingId + "]")
@@ -207,23 +238,19 @@ class ScreenshareManager(val aSystem: ActorSystem, val bus: IEventsMessageBus)
       log.debug("Received start share request message for meeting=[" + msg.meetingId + "]")
     }
     screenshares.get(msg.meetingId) match {
-      case None => {
+      case None =>
         if (log.isDebugEnabled) {
-          log.debug("Creating screenshare=[" + msg.meetingId + "]")
+          log.warning("Reqeusting to share on non-existing meeting with id=[" + msg.meetingId + "]")
         }
-        val activeScreenshare = ActiveScreenshare(this, bus, msg.meetingId)
-        screenshares += msg.meetingId -> activeScreenshare
+        bus.send(new StartShareRequestFailedResponse(msg.meetingId, msg.userId, "UNKNOWN_MEETING"))
 
-        activeScreenshare.actorRef forward msg
-      }
-      case Some(screenshare) => {
+      case Some(screenshare) =>
         if (log.isDebugEnabled) {
-          log.debug("Screenshare already exists. screenshare=[" + msg.meetingId + "]")
+          log.debug("Request to start screenshare=[" + msg.meetingId + "]")
         }
 
         screenshare.actorRef forward msg
 
-      }
     }
   }
 
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/Session.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/Session.scala
index ced6ad001529d0403f216dfca1dae4dbbc8b6abc..e5c3f6cb77f711e2b7c4580d7c00767f8d8efe4d 100755
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/Session.scala
+++ b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/Session.scala
@@ -18,14 +18,13 @@
 */
 package org.bigbluebutton.app.screenshare.server.sessions
 
-import akka.actor.{ActorLogging, Actor, Props}
+import akka.actor.{Actor, ActorLogging, Props}
+import org.bigbluebutton.app.screenshare.StreamInfo
 import org.bigbluebutton.app.screenshare.server.sessions.Session.KeepAliveTimeout
 import org.bigbluebutton.app.screenshare.server.util.TimeUtil
 import org.bigbluebutton.app.screenshare.server.sessions.messages._
-import org.bigbluebutton.app.screenshare.events.IEventsMessageBus
-import org.bigbluebutton.app.screenshare.events.ShareStoppedEvent
-import org.bigbluebutton.app.screenshare.events.StreamStoppedEvent
-import org.bigbluebutton.app.screenshare.events.StreamStartedEvent
+import org.bigbluebutton.app.screenshare.events._
+
 import scala.concurrent.duration._
 
 object Session {
@@ -116,7 +115,10 @@ class Session(parent: Screenshare,
       w <- width
       h <- height
       url <- streamUrl
-    } yield (sender ! new IsScreenSharingReply(true, streamId, w, h, url))
+    } yield {
+      val info = new StreamInfo(true, streamId, w, h, url)
+      bus.send(new IsScreenSharingResponse(meetingId, msg.userId, info))
+    }
 
   }
 
diff --git a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/messages/IMessage.scala b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/messages/IMessage.scala
index e8ccb71c30654f772c3fc6d3528776e26442a41c..98320b74de024bfc392a711fe7b3f6acdfd7dad6 100755
--- a/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/messages/IMessage.scala
+++ b/bbb-screenshare/app/src/main/scala/org/bigbluebutton/app/screenshare/server/sessions/messages/IMessage.scala
@@ -1,6 +1,6 @@
 package org.bigbluebutton.app.screenshare.server.sessions.messages
 
-case class StartShareRequestMessage(meetingId: String, userId: String, record: Boolean)
+case class StartShareRequestMessage(meetingId: String, userId: String, jnlp: String, record: Boolean)
 
 case class StartShareRequestReplyMessage(token: String, streamId: String)
 
@@ -28,7 +28,7 @@ case class GetSharingStatusReply(status: String, streamId: Option[String])
 
 case class UpdateShareStatus(meetingId: String, streamId: String, sequence: Int)
 
-case class IsScreenSharing(meetingId: String)
+case class IsScreenSharing(meetingId: String, userId: String)
 
 case class IsScreenSharingReply(sharing: Boolean, streamId: String, 
                                   width: Int, height: Int, url: String)
@@ -39,4 +39,8 @@ case class ScreenShareInfoRequestReply(meetingId: String, streamId: String)
 
 case class UserDisconnected(meetingId: String, userId: String)
 
-case class UserConnected(meetingId: String, userId: String)
\ No newline at end of file
+case class UserConnected(meetingId: String, userId: String)
+
+case class MeetingHasEnded(meetingId: String)
+
+case class MeetingCreated(meetingId: String)
\ No newline at end of file
diff --git a/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-red5-redis-pubsub.xml b/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-red5-redis-pubsub.xml
new file mode 100755
index 0000000000000000000000000000000000000000..c64c2974aa5fc79bdf5cc5d0b8a690352921f9c9
--- /dev/null
+++ b/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-red5-redis-pubsub.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+
+Copyright (c) 2014 BigBlueButton Inc. and by respective authors (see below).
+
+This program is free software; you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 3.0 of the License, or (at your option) any later
+version.
+
+BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:util="http://www.springframework.org/schema/util"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+			http://www.springframework.org/schema/util
+			http://www.springframework.org/schema/util/spring-util-2.0.xsd
+			">
+
+    <bean id="red5RedisSender"
+          class="org.bigbluebutton.app.screenshare.messaging.redis.MessageSender"
+                    init-method="start" destroy-method="stop">
+      <property name="host" value="${redis.host}" />
+      <property name="port" value="${redis.port}" />
+    </bean>
+
+    <bean id="red5RedisReceiver" class="org.bigbluebutton.app.screenshare.messaging.redis.MessageReceiver"
+                    init-method="start" destroy-method="stop">
+      <property name="messageHandler"> <ref local="red5RedisHandler"/> </property>
+      <property name="host" value="${redis.host}" />
+      <property name="port" value="${redis.port}" />
+    </bean>
+
+    <bean id="red5RedisHandler" class="org.bigbluebutton.app.screenshare.messaging.redis.ReceivedMessageHandler"
+                    init-method="start" destroy-method="stop">
+      <property name="messageDistributor"><ref bean="red5RedisDistributor" /></property>
+    </bean>
+
+    <bean id="red5RedisDistributor" class="org.bigbluebutton.app.screenshare.messaging.redis.MessageDistributor">
+       <property name="messageHandler"> <ref local="red5RedisHandler"/> </property>
+       <property name="messageListeners">
+          <set>
+              <ref bean="redisPubSubMessageHandler" />
+          </set>
+      </property>
+    </bean>
+
+</beans>
diff --git a/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-redis-pool.xml b/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-redis-pool.xml
new file mode 100755
index 0000000000000000000000000000000000000000..eae411543fed0d67cb1317a28759ec6add1cc36a
--- /dev/null
+++ b/bbb-screenshare/app/src/main/webapp/WEB-INF/bbb-redis-pool.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+
+Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+
+This program is free software; you can redistribute it and/or modify it under the
+terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 3.0 of the License, or (at your option) any later
+version.
+
+BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:util="http://www.springframework.org/schema/util"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+			http://www.springframework.org/schema/util 
+			http://www.springframework.org/schema/util/spring-util-2.0.xsd
+			">
+
+	<bean id="redisPool" class="redis.clients.jedis.JedisPool">
+		<constructor-arg index="0" value="${redis.host}"/>
+		<constructor-arg index="1" value="${redis.port}"/>
+	</bean>
+
+</beans>
diff --git a/bbb-screenshare/app/src/main/webapp/WEB-INF/red5-web.xml b/bbb-screenshare/app/src/main/webapp/WEB-INF/red5-web.xml
index 5095085b619423b79356da4b7b708a9c3b733464..0e6048703c0fa6e6258e5cace2d54de8dbfd50f7 100755
--- a/bbb-screenshare/app/src/main/webapp/WEB-INF/red5-web.xml
+++ b/bbb-screenshare/app/src/main/webapp/WEB-INF/red5-web.xml
@@ -56,8 +56,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
   
   <bean id="screenshare.service" class="org.bigbluebutton.app.screenshare.red5.Red5AppService">
     <property name="appHandler" ref="red5AppHandler"/>
+    <property name="red5RedisSender" ref="red5RedisSender"/>
   </bean>
-  
+
   <bean id="red5AppHandler" class="org.bigbluebutton.app.screenshare.red5.Red5AppHandler">
     <property name="application" ref="screenShareApplication"/>
     <property name="messageSender" ref="connectionInvokerService"/>
@@ -107,4 +108,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
     <constructor-arg index="0" value="${redis.host}"/>
     <constructor-arg index="1" value="${redis.port}"/>
   </bean>
+
+    <bean id="redisPubSubMessageHandler"
+          class="org.bigbluebutton.app.screenshare.messaging.redis.RedisPubSubMessageHandler">
+        <property name="appHandler" ref="red5AppHandler"/>
+    </bean>
+
+  <import resource="bbb-redis-pool.xml"/>
+  <import resource="bbb-red5-redis-pubsub.xml"/>
 </beans>
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/MessageReceiver.as b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/MessageReceiver.as
index 9e6c5ec4b39a8464cbe5087e23f902c126bf1f50..1d6065cf5dbe1e6f7508b5906ae91e61ce69c521 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/MessageReceiver.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/screenshare/services/MessageReceiver.as
@@ -69,6 +69,9 @@ package org.bigbluebutton.modules.screenshare.services
         case "pauseScreenSharingEvent":
           handlePauseScreenSharingEvent(message);
           break;
+        case "startShareRequestRejectedResponse":
+          handleStartShareRequestRejectedResponse(message);
+          break;
         default:
 //          LogUtil.warn("Cannot handle message [" + messageName + "]");
       }
@@ -83,6 +86,12 @@ package org.bigbluebutton.modules.screenshare.services
       } 
     }
 
+    private function handleStartShareRequestRejectedResponse(message:Object):void {
+      LOGGER.debug("handleStartShareRequestRejectedResponse " + message);      
+      var shareFailedEvent: ShareStartRequestResponseEvent = new ShareStartRequestResponseEvent(null, null, null, false);
+      dispatcher.dispatchEvent(shareFailedEvent);         
+    }
+    
     private function handleStartShareRequestResponse(message:Object):void {
       LOGGER.debug("handleStartShareRequestResponse " + message);      
       var map:Object = JSON.parse(message.msg);