From 6effca3389118db216a1c37214cb39efbd756535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Jou=C3=9Fen?= Date: Mon, 9 Jul 2018 15:42:55 +0200 Subject: [PATCH 1/9] Introduced class utils to collect general reusable functions --- .../java/io/openvidu/server/core/Utils.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 openvidu-server/src/main/java/io/openvidu/server/core/Utils.java diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Utils.java b/openvidu-server/src/main/java/io/openvidu/server/core/Utils.java new file mode 100644 index 0000000000..fbaf6f0cd0 --- /dev/null +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Utils.java @@ -0,0 +1,24 @@ +package io.openvidu.server.core; + +import org.apache.commons.lang3.RandomStringUtils; + +public class Utils { + + /** + * Generate a random alpha numeric key chain + * @return + */ + public String generateRandomChain() { + return RandomStringUtils.randomAlphanumeric(16).toLowerCase(); + } + + /** + * Check that the metadata only has a max length of 10000 chars. + * + * @param metadata + * @return + */ + public boolean isMetadataFormatCorrect(String metadata) { + return (metadata.length() <= 10000); + } +} From 6a1a8ea1729d2878748b22f7ce6994a0e7107cdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Jou=C3=9Fen?= Date: Mon, 9 Jul 2018 15:43:20 +0200 Subject: [PATCH 2/9] Introduced SessionStorage which is an extract of the SessionManager --- .../openvidu/server/core/SessionStorage.java | 307 ++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java new file mode 100644 index 0000000000..a0817f397e --- /dev/null +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java @@ -0,0 +1,307 @@ +package io.openvidu.server.core; + +import io.openvidu.client.OpenViduException; +import io.openvidu.client.internal.ProtocolElements; +import io.openvidu.java.client.SessionProperties; +import io.openvidu.server.OpenViduServer; +import io.openvidu.server.coturn.CoturnCredentialsService; +import io.openvidu.server.coturn.TurnCredentials; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public class SessionStorage { + + private static final Logger log = LoggerFactory.getLogger(SessionStorage.class); + + @Autowired + private Utils utils; + + @Autowired + private CoturnCredentialsService coturnCredentialsService; + + protected ConcurrentMap sessions = new ConcurrentHashMap<>(); + protected ConcurrentMap sessionProperties = new ConcurrentHashMap<>(); + protected ConcurrentMap> sessionidParticipantpublicidParticipant = new ConcurrentHashMap<>(); + protected ConcurrentMap insecureUsers = new ConcurrentHashMap<>(); + protected ConcurrentMap> sessionidTokenTokenobj = new ConcurrentHashMap<>(); + + /** + * Returns a Session given its id + * + * @return Session + */ + public Session getSession(String sessionId) { + return sessions.get(sessionId); + } + + /** + * Returns all currently active (opened) sessions. + * + * @return set of the session's identifiers + */ + public Set getSessions() { + return new HashSet(sessions.keySet()); + } + + /** + * Returns all currently active (opened) sessions. + * + * @return set of the session's identifiers + */ + public Collection getSessionObjects() { + return sessions.values(); + } + + public Session putSessionIfAbsent(String sessionId, Session session) { return sessions.putIfAbsent(sessionId, session); } + + public SessionProperties getSessionProperties(String sessionId) { return this.sessionProperties.get(sessionId); } + + /** + * Returns all the participants inside a session. + * + * @param sessionId + * identifier of the session + * @return set of {@link Participant} + * @throws OpenViduException + * in case the session doesn't exist + */ + public Set getParticipants(String sessionId) throws OpenViduException { + Session session = sessions.get(sessionId); + if (session == null) { + throw new OpenViduException(OpenViduException.Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId + "' not found"); + } + Set participants = session.getParticipants(); + participants.removeIf(p -> p.isClosed()); + return participants; + } + + /** + * Returns a participant in a session + * + * @param sessionId + * identifier of the session + * @param participantPrivateId + * private identifier of the participant + * @return {@link Participant} + * @throws OpenViduException + * in case the session doesn't exist or the participant doesn't + * belong to it + */ + public Participant getParticipant(String sessionId, String participantPrivateId) throws OpenViduException { + Session session = sessions.get(sessionId); + if (session == null) { + throw new OpenViduException(OpenViduException.Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId + "' not found"); + } + Participant participant = session.getParticipantByPrivateId(participantPrivateId); + if (participant == null) { + throw new OpenViduException(OpenViduException.Code.USER_NOT_FOUND_ERROR_CODE, + "Participant '" + participantPrivateId + "' not found in session '" + sessionId + "'"); + } + return participant; + } + + /** + * Returns a participant + * + * @param participantPrivateId + * private identifier of the participant + * @return {@link Participant} + * @throws OpenViduException + * in case the participant doesn't exist + */ + public Participant getParticipant(String participantPrivateId) throws OpenViduException { + for (Session session : sessions.values()) { + if (!session.isClosed()) { + if (session.getParticipantByPrivateId(participantPrivateId) != null) { + return session.getParticipantByPrivateId(participantPrivateId); + } + } + } + throw new OpenViduException(OpenViduException.Code.USER_NOT_FOUND_ERROR_CODE, + "No participant with private id '" + participantPrivateId + "' was found"); + } + + public void storeSessionId(String sessionId, SessionProperties sessionProperties) { + this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>()); + this.sessionProperties.putIfAbsent(sessionId, sessionProperties); + showTokens(); + } + + public ConcurrentHashMap putTokenObject(String sessionId, ConcurrentHashMap map) { + return this.sessionidTokenTokenobj.putIfAbsent(sessionId, map); + } + + public void removeTokenObject(String sessionId) { + this.sessionidTokenTokenobj.remove(sessionId); + } + + public ConcurrentHashMap getTokenObject(String sessionId) { + return this.sessionidTokenTokenobj.get(sessionId); + } + + public String newToken(String sessionId, ParticipantRole role, String serverMetadata) throws OpenViduException { + ConcurrentHashMap map = this.putTokenObject(sessionId, new ConcurrentHashMap<>()); + + if (map != null) { + + if (!utils.isMetadataFormatCorrect(serverMetadata)) { + log.error("Data invalid format. Max length allowed is 10000 chars"); + throw new OpenViduException(OpenViduException.Code.GENERIC_ERROR_CODE, + "Data invalid format. Max length allowed is 10000 chars"); + } + + String token = OpenViduServer.publicUrl; + token += "?sessionId=" + sessionId; + token += "&token=" + utils.generateRandomChain(); + token += "&role=" + role.name(); + TurnCredentials turnCredentials = null; + if (this.coturnCredentialsService.isCoturnAvailable()) { + turnCredentials = coturnCredentialsService.createUser(); + if (turnCredentials != null) { + token += "&turnUsername=" + turnCredentials.getUsername(); + token += "&turnCredential=" + turnCredentials.getCredential(); + } + } + Token t = new Token(token, role, serverMetadata, turnCredentials); + + map.putIfAbsent(token, t); + this.showTokens(); + return token; + + } else { + this.removeTokenObject(sessionId); + log.error("sessionId [" + sessionId + "] is not valid"); + throw new OpenViduException(OpenViduException.Code.ROOM_NOT_FOUND_ERROR_CODE, "sessionId [" + sessionId + "] not found"); + } + } + + public boolean isTokenValidInSession(String token, String sessionId, String participanPrivatetId) { + if (!this.isInsecureParticipant(participanPrivatetId)) { + if (this.sessionidTokenTokenobj.get(sessionId) != null) { + return this.sessionidTokenTokenobj.get(sessionId).containsKey(token); + } else { + return false; + } + } else { + this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>()); + this.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>()); + this.sessionidTokenTokenobj.get(sessionId).putIfAbsent(token, + new Token(token, ParticipantRole.PUBLISHER, "", + this.coturnCredentialsService.isCoturnAvailable() + ? this.coturnCredentialsService.createUser() + : null)); + return true; + } + } + + public boolean isParticipantInSession(String sessionId, Participant participant) { + Session session = this.sessions.get(sessionId); + if (session != null) { + return (session.getParticipantByPrivateId(participant.getParticipantPrivateId()) != null); + } else { + throw new OpenViduException(OpenViduException.Code.ROOM_NOT_FOUND_ERROR_CODE, "[" + sessionId + "] is not a valid sessionId"); + } + } + + public boolean isPublisherInSession(String sessionId, Participant participant) { + if (!this.isInsecureParticipant(participant.getParticipantPrivateId())) { + if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { + return (ParticipantRole.PUBLISHER.equals(participant.getToken().getRole()) + || ParticipantRole.MODERATOR.equals(participant.getToken().getRole())); + } else { + return false; + } + } else { + return true; + } + } + + public boolean isInsecureParticipant(String participantPrivateId) { + if (this.insecureUsers.containsKey(participantPrivateId)) { + log.info("The user with private id {} is an INSECURE user", participantPrivateId); + return true; + } + return false; + } + + public void newInsecureParticipant(String participantPrivateId) { + this.insecureUsers.put(participantPrivateId, true); + } + + public void removeInsecureParticipant(String participantPrivateId) { + this.insecureUsers.remove(participantPrivateId); + } + + public ConcurrentHashMap getPublicIdParticipantMap(String sessionId) { + return this.sessionidParticipantpublicidParticipant.get(sessionId); + } + + public Participant newParticipant(String sessionId, String participantPrivatetId, Token token, + String clientMetadata) { + if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { + String participantPublicId = utils.generateRandomChain(); + Participant p = new Participant(participantPrivatetId, participantPublicId, token, clientMetadata); + while (this.sessionidParticipantpublicidParticipant.get(sessionId).putIfAbsent(participantPublicId, + p) != null) { + participantPublicId = utils.generateRandomChain(); + p.setParticipantPublicId(participantPublicId); + } + return p; + } else { + throw new OpenViduException(OpenViduException.Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId); + } + } + + public Participant newRecorderParticipant(String sessionId, String participantPrivatetId, Token token, + String clientMetadata) { + if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { + Participant p = new Participant(participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, + token, clientMetadata); + this.sessionidParticipantpublicidParticipant.get(sessionId) + .put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p); + return p; + } else { + throw new OpenViduException(OpenViduException.Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId); + } + } + + public Token consumeToken(String sessionId, String participantPrivateId, String token) { + if (this.sessionidTokenTokenobj.get(sessionId) != null) { + Token t = this.sessionidTokenTokenobj.get(sessionId).remove(token); + if (t != null) { + return t; + } else { + throw new OpenViduException(OpenViduException.Code.TOKEN_CANNOT_BE_CREATED_ERROR_CODE, sessionId); + } + } else { + throw new OpenViduException(OpenViduException.Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId); + } + } + + public void emptyCollections(Session session) { + sessions.remove(session.getSessionId()); + + sessionProperties.remove(session.getSessionId()); + sessionidParticipantpublicidParticipant.remove(session.getSessionId()); + sessionidTokenTokenobj.remove(session.getSessionId()); + + log.warn("Session '{}' removed and closed", session.getSessionId()); + } + + public void showTokens() { log.info(": {}", this.sessionidTokenTokenobj.toString()); } + + public void showInsecureParticipants() { + log.info(": {}", this.insecureUsers.toString()); + } + + public void showAllParticipants() { + log.info(": {}", this.sessionidParticipantpublicidParticipant.toString()); + } +} From b05b5c56574477cdd1cb2799acfd6588a3a08901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Jou=C3=9Fen?= Date: Mon, 9 Jul 2018 15:44:00 +0200 Subject: [PATCH 3/9] Add Utils and SessionStorage as Bean to OpenViduServer to enable autowiring --- .../main/java/io/openvidu/server/OpenViduServer.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java index 70fac13980..65fdc05692 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java +++ b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java @@ -25,6 +25,8 @@ import javax.annotation.PostConstruct; import javax.ws.rs.ProcessingException; +import io.openvidu.server.core.SessionStorage; +import io.openvidu.server.core.Utils; import org.kurento.jsonrpc.JsonUtils; import org.kurento.jsonrpc.internal.server.config.JsonRpcConfiguration; import org.kurento.jsonrpc.server.JsonRpcConfigurer; @@ -153,6 +155,14 @@ public CoturnCredentialsService coturnCredentialsService() { return new CoturnCredentialsServiceFactory(openviduConfig()).getCoturnCredentialsService(); } + @Bean + @ConditionalOnMissingBean + public SessionStorage sessionStorage() { return new SessionStorage(); } + + @Bean + @ConditionalOnMissingBean + public Utils utils() { return new Utils(); } + @Override public void registerJsonRpcHandlers(JsonRpcHandlerRegistry registry) { registry.addHandler(rpcHandler().withPingWatchdog(true), "/openvidu"); From e4eff71bf572f626688c8a036231328fca47fa15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Jou=C3=9Fen?= Date: Mon, 9 Jul 2018 15:45:24 +0200 Subject: [PATCH 4/9] Use the SessionStorage in SessionManager and remove duplicated code. Adjut KurentoSessionManager and SessionRestController --- .../openvidu/server/core/SessionManager.java | 179 +++--------------- .../kurento/core/KurentoSessionManager.java | 22 +-- .../server/rest/SessionRestController.java | 12 +- 3 files changed, 41 insertions(+), 172 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index 224837f7a7..124e1ce76a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -64,11 +64,8 @@ public abstract class SessionManager { @Autowired protected CoturnCredentialsService coturnCredentialsService; - protected ConcurrentMap sessions = new ConcurrentHashMap<>(); - protected ConcurrentMap sessionProperties = new ConcurrentHashMap<>(); - protected ConcurrentMap> sessionidParticipantpublicidParticipant = new ConcurrentHashMap<>(); - protected ConcurrentMap insecureUsers = new ConcurrentHashMap<>(); - public ConcurrentMap> sessionidTokenTokenobj = new ConcurrentHashMap<>(); + @Autowired + protected SessionStorage sessionStorage; private volatile boolean closed = false; @@ -104,7 +101,7 @@ public abstract void evictParticipant(Participant evictedParticipant, Participan * @return Session */ public Session getSession(String sessionId) { - return sessions.get(sessionId); + return this.sessionStorage.getSession(sessionId); } /** @@ -113,7 +110,7 @@ public Session getSession(String sessionId) { * @return set of the session's identifiers */ public Set getSessions() { - return new HashSet(sessions.keySet()); + return this.sessionStorage.getSessions(); } /** @@ -122,7 +119,7 @@ public Set getSessions() { * @return set of the session's identifiers */ public Collection getSessionObjects() { - return sessions.values(); + return this.sessionStorage.getSessionObjects(); } /** @@ -135,13 +132,7 @@ public Collection getSessionObjects() { * in case the session doesn't exist */ public Set getParticipants(String sessionId) throws OpenViduException { - Session session = sessions.get(sessionId); - if (session == null) { - throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId + "' not found"); - } - Set participants = session.getParticipants(); - participants.removeIf(p -> p.isClosed()); - return participants; + return this.sessionStorage.getParticipants(sessionId); } /** @@ -157,16 +148,7 @@ public Set getParticipants(String sessionId) throws OpenViduExcepti * belong to it */ public Participant getParticipant(String sessionId, String participantPrivateId) throws OpenViduException { - Session session = sessions.get(sessionId); - if (session == null) { - throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId + "' not found"); - } - Participant participant = session.getParticipantByPrivateId(participantPrivateId); - if (participant == null) { - throw new OpenViduException(Code.USER_NOT_FOUND_ERROR_CODE, - "Participant '" + participantPrivateId + "' not found in session '" + sessionId + "'"); - } - return participant; + return this.sessionStorage.getParticipant(sessionId, participantPrivateId); } /** @@ -179,15 +161,7 @@ public Participant getParticipant(String sessionId, String participantPrivateId) * in case the participant doesn't exist */ public Participant getParticipant(String participantPrivateId) throws OpenViduException { - for (Session session : sessions.values()) { - if (!session.isClosed()) { - if (session.getParticipantByPrivateId(participantPrivateId) != null) { - return session.getParticipantByPrivateId(participantPrivateId); - } - } - } - throw new OpenViduException(Code.USER_NOT_FOUND_ERROR_CODE, - "No participant with private id '" + participantPrivateId + "' was found"); + return this.sessionStorage.getParticipant(participantPrivateId); } public MediaOptions generateMediaOptions(Request request) { @@ -195,88 +169,23 @@ public MediaOptions generateMediaOptions(Request request) { } public void storeSessionId(String sessionId, SessionProperties sessionProperties) { - this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>()); - this.sessionProperties.putIfAbsent(sessionId, sessionProperties); - showTokens(); + this.sessionStorage.storeSessionId(sessionId, sessionProperties); } public String newToken(String sessionId, ParticipantRole role, String serverMetadata) throws OpenViduException { - - ConcurrentHashMap map = this.sessionidTokenTokenobj.putIfAbsent(sessionId, - new ConcurrentHashMap<>()); - if (map != null) { - - if (!isMetadataFormatCorrect(serverMetadata)) { - log.error("Data invalid format. Max length allowed is 10000 chars"); - throw new OpenViduException(Code.GENERIC_ERROR_CODE, - "Data invalid format. Max length allowed is 10000 chars"); - } - - String token = OpenViduServer.publicUrl; - token += "?sessionId=" + sessionId; - token += "&token=" + this.generateRandomChain(); - token += "&role=" + role.name(); - TurnCredentials turnCredentials = null; - if (this.coturnCredentialsService.isCoturnAvailable()) { - turnCredentials = coturnCredentialsService.createUser(); - if (turnCredentials != null) { - token += "&turnUsername=" + turnCredentials.getUsername(); - token += "&turnCredential=" + turnCredentials.getCredential(); - } - } - Token t = new Token(token, role, serverMetadata, turnCredentials); - - map.putIfAbsent(token, t); - showTokens(); - return token; - - } else { - this.sessionidTokenTokenobj.remove(sessionId); - log.error("sessionId [" + sessionId + "] is not valid"); - throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "sessionId [" + sessionId + "] not found"); - } - + return this.sessionStorage.newToken(sessionId, role, serverMetadata); } public boolean isTokenValidInSession(String token, String sessionId, String participanPrivatetId) { - if (!this.isInsecureParticipant(participanPrivatetId)) { - if (this.sessionidTokenTokenobj.get(sessionId) != null) { - return this.sessionidTokenTokenobj.get(sessionId).containsKey(token); - } else { - return false; - } - } else { - this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>()); - this.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>()); - this.sessionidTokenTokenobj.get(sessionId).putIfAbsent(token, - new Token(token, ParticipantRole.PUBLISHER, "", - this.coturnCredentialsService.isCoturnAvailable() - ? this.coturnCredentialsService.createUser() - : null)); - return true; - } + return this.sessionStorage.isTokenValidInSession(token, sessionId, participanPrivatetId); } public boolean isParticipantInSession(String sessionId, Participant participant) { - Session session = this.sessions.get(sessionId); - if (session != null) { - return (session.getParticipantByPrivateId(participant.getParticipantPrivateId()) != null); - } else { - throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "[" + sessionId + "] is not a valid sessionId"); - } + return this.sessionStorage.isParticipantInSession(sessionId, participant); } public boolean isPublisherInSession(String sessionId, Participant participant) { - if (!this.isInsecureParticipant(participant.getParticipantPrivateId())) { - if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - return (ParticipantRole.PUBLISHER.equals(participant.getToken().getRole()) - || ParticipantRole.MODERATOR.equals(participant.getToken().getRole())); - } else { - return false; - } - } else { - return true; - } + return this.sessionStorage.isPublisherInSession(sessionId, participant); } public boolean isModeratorInSession(String sessionId, Participant participant) { @@ -292,11 +201,7 @@ public boolean isModeratorInSession(String sessionId, Participant participant) { } public boolean isInsecureParticipant(String participantPrivateId) { - if (this.insecureUsers.containsKey(participantPrivateId)) { - log.info("The user with private id {} is an INSECURE user", participantPrivateId); - return true; - } - return false; + return this.sessionStorage.isInsecureParticipant(participantPrivateId); } public boolean isMetadataFormatCorrect(String metadata) { @@ -305,62 +210,30 @@ public boolean isMetadataFormatCorrect(String metadata) { } public void newInsecureParticipant(String participantPrivateId) { - this.insecureUsers.put(participantPrivateId, true); + this.sessionStorage.newInsecureParticipant(participantPrivateId); } public Participant newParticipant(String sessionId, String participantPrivatetId, Token token, String clientMetadata) { - if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - String participantPublicId = this.generateRandomChain(); - Participant p = new Participant(participantPrivatetId, participantPublicId, token, clientMetadata); - while (this.sessionidParticipantpublicidParticipant.get(sessionId).putIfAbsent(participantPublicId, - p) != null) { - participantPublicId = this.generateRandomChain(); - p.setParticipantPublicId(participantPublicId); - } - return p; - } else { - throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId); - } + return this.sessionStorage.newParticipant(sessionId, participantPrivatetId, token, clientMetadata); } public Participant newRecorderParticipant(String sessionId, String participantPrivatetId, Token token, String clientMetadata) { - if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - Participant p = new Participant(participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, - token, clientMetadata); - this.sessionidParticipantpublicidParticipant.get(sessionId) - .put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p); - return p; - } else { - throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId); - } + return this.sessionStorage.newRecorderParticipant(sessionId, participantPrivatetId, token, clientMetadata); } public Token consumeToken(String sessionId, String participantPrivateId, String token) { - if (this.sessionidTokenTokenobj.get(sessionId) != null) { - Token t = this.sessionidTokenTokenobj.get(sessionId).remove(token); - if (t != null) { - return t; - } else { - throw new OpenViduException(Code.TOKEN_CANNOT_BE_CREATED_ERROR_CODE, sessionId); - } - } else { - throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId); - } + return this.sessionStorage.consumeToken(sessionId, participantPrivateId, token); } - public void showTokens() { - log.info(": {}", this.sessionidTokenTokenobj.toString()); - } + public void showTokens() { this.sessionStorage.showTokens(); } public void showInsecureParticipants() { - log.info(": {}", this.insecureUsers.toString()); + this.sessionStorage.showInsecureParticipants(); } - public void showAllParticipants() { - log.info(": {}", this.sessionidParticipantpublicidParticipant.toString()); - } + public void showAllParticipants() { this.sessionStorage.showAllParticipants(); } public String generateRandomChain() { return RandomStringUtils.randomAlphanumeric(16).toLowerCase(); @@ -379,7 +252,7 @@ public String generateRandomChain() { public void close() { closed = true; log.info("Closing all sessions"); - for (String sessionId : sessions.keySet()) { + for (String sessionId : this.sessionStorage.getSessions()) { try { closeSession(sessionId, "openviduServerStopped"); } catch (Exception e) { @@ -405,7 +278,7 @@ public void close() { * in case the session doesn't exist or has been already closed */ public Set closeSession(String sessionId, String reason) { - Session session = sessions.get(sessionId); + Session session = this.sessionStorage.getSession(sessionId); if (session == null) { throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId + "' not found"); } @@ -434,11 +307,7 @@ public void closeSessionAndEmptyCollections(Session session, String reason) { if (session.close(reason)) { sessionEventsHandler.onSessionClosed(session.getSessionId(), reason); } - sessions.remove(session.getSessionId()); - - sessionProperties.remove(session.getSessionId()); - sessionidParticipantpublicidParticipant.remove(session.getSessionId()); - sessionidTokenTokenobj.remove(session.getSessionId()); + this.sessionStorage.emptyCollections(session); log.warn("Session '{}' removed and closed", session.getSessionId()); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index 019b6af35a..6e01263d4d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -70,10 +70,10 @@ public synchronized void joinRoom(Participant participant, String sessionId, Int KurentoClientSessionInfo kcSessionInfo = new OpenViduKurentoClientSessionInfo( participant.getParticipantPrivateId(), sessionId); - KurentoSession session = (KurentoSession) sessions.get(sessionId); + KurentoSession session = (KurentoSession) this.sessionStorage.getSession(sessionId); if (session == null && kcSessionInfo != null) { - SessionProperties properties = sessionProperties.get(sessionId); + SessionProperties properties = this.sessionStorage.getSessionProperties(sessionId); if (properties == null && this.isInsecureParticipant(participant.getParticipantPrivateId())) { properties = new SessionProperties.Builder().mediaMode(MediaMode.ROUTED) .recordingMode(RecordingMode.ALWAYS).defaultRecordingLayout(RecordingLayout.BEST_FIT) @@ -81,7 +81,7 @@ public synchronized void joinRoom(Participant participant, String sessionId, Int } createSession(kcSessionInfo, properties); } - session = (KurentoSession) sessions.get(sessionId); + session = (KurentoSession) this.sessionStorage.getSession(sessionId); if (session == null) { log.warn("Session '{}' not found"); throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId @@ -125,26 +125,26 @@ public synchronized void leaveRoom(Participant participant, Integer transactionI // Update control data structures - if (sessionidParticipantpublicidParticipant.get(sessionId) != null) { - Participant p = sessionidParticipantpublicidParticipant.get(sessionId) + if (this.sessionStorage.getPublicIdParticipantMap(sessionId) != null) { + Participant p = this.sessionStorage.getPublicIdParticipantMap(sessionId) .remove(participant.getParticipantPublicId()); if (this.coturnCredentialsService.isCoturnAvailable()) { this.coturnCredentialsService.deleteUser(p.getToken().getTurnCredentials().getUsername()); } - if (sessionidTokenTokenobj.get(sessionId) != null) { - sessionidTokenTokenobj.get(sessionId).remove(p.getToken().getToken()); + if (this.sessionStorage.getTokenObject(sessionId) != null) { + this.sessionStorage.getTokenObject(sessionId).remove(p.getToken().getToken()); } boolean stillParticipant = false; - for (Session s : sessions.values()) { + for (Session s : this.sessionStorage.getSessionObjects()) { if (s.getParticipantByPrivateId(p.getParticipantPrivateId()) != null) { stillParticipant = true; break; } } if (!stillParticipant) { - insecureUsers.remove(p.getParticipantPrivateId()); + this.sessionStorage.removeInsecureParticipant(p.getParticipantPrivateId()); } } @@ -437,7 +437,7 @@ public void onIceCandidate(Participant participant, String endpointName, String public void createSession(KurentoClientSessionInfo kcSessionInfo, SessionProperties sessionProperties) throws OpenViduException { String sessionId = kcSessionInfo.getRoomName(); - KurentoSession session = (KurentoSession) sessions.get(sessionId); + KurentoSession session = (KurentoSession) this.sessionStorage.getSession(sessionId); if (session != null) { throw new OpenViduException(Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE, "Session '" + sessionId + "' already exists"); @@ -446,7 +446,7 @@ public void createSession(KurentoClientSessionInfo kcSessionInfo, SessionPropert session = new KurentoSession(sessionId, sessionProperties, kurentoClient, kurentoSessionEventsHandler, kcProvider.destroyWhenUnused(), this.CDR, this.openviduConfig); - KurentoSession oldSession = (KurentoSession) sessions.putIfAbsent(sessionId, session); + KurentoSession oldSession = (KurentoSession) this.sessionStorage.putSessionIfAbsent(sessionId, session); if (oldSession != null) { log.warn("Session '{}' has just been created by another thread", sessionId); return; diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 49b5af8c00..17c74a87a3 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -22,6 +22,7 @@ import java.util.NoSuchElementException; import java.util.concurrent.ConcurrentHashMap; +import io.openvidu.server.core.*; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.springframework.beans.factory.annotation.Autowired; @@ -43,10 +44,6 @@ import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.SessionProperties; import io.openvidu.server.config.OpenviduConfig; -import io.openvidu.server.core.Participant; -import io.openvidu.server.core.ParticipantRole; -import io.openvidu.server.core.Session; -import io.openvidu.server.core.SessionManager; import io.openvidu.server.recording.ComposedRecordingService; import io.openvidu.server.recording.Recording; @@ -62,6 +59,9 @@ public class SessionRestController { @Autowired private SessionManager sessionManager; + @Autowired + private SessionStorage sessionStorage; + @Autowired private ComposedRecordingService recordingService; @@ -120,13 +120,13 @@ public ResponseEntity getSessionId(@RequestBody(required = false) Ma String sessionId; if (customSessionId != null && !customSessionId.isEmpty()) { - if (sessionManager.sessionidTokenTokenobj.putIfAbsent(customSessionId, new ConcurrentHashMap<>()) != null) { + if (this.sessionStorage.putTokenObject(customSessionId, new ConcurrentHashMap<>()) != null) { return new ResponseEntity<>(HttpStatus.CONFLICT); } sessionId = customSessionId; } else { sessionId = sessionManager.generateRandomChain(); - sessionManager.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>()); + this.sessionStorage.putTokenObject(sessionId, new ConcurrentHashMap<>()); } sessionManager.storeSessionId(sessionId, sessionProperties); From d50a5806d85ea5a39eda6d809df19db291def302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Jou=C3=9Fen?= Date: Mon, 9 Jul 2018 15:51:04 +0200 Subject: [PATCH 5/9] Introduce a SessionManagerProvider object to provide a SessionManager based on the used MediaMode --- .../server/core/SessionManagerProvider.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 openvidu-server/src/main/java/io/openvidu/server/core/SessionManagerProvider.java diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManagerProvider.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManagerProvider.java new file mode 100644 index 0000000000..8c90fe6405 --- /dev/null +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManagerProvider.java @@ -0,0 +1,30 @@ +package io.openvidu.server.core; + +import io.openvidu.java.client.MediaMode; +import io.openvidu.java.client.SessionProperties; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.xml.ws.spi.WebServiceFeatureAnnotation; + +public class SessionManagerProvider { + + @Autowired + private SessionManager sessionManager; + + @Autowired + private SessionStorage sessionStorage; + + public SessionManager get(MediaMode mediaMode) { + if(mediaMode == MediaMode.RELAYED) { + // Implement SessionManager for MediaMode.RELAYED + } + + return this.sessionManager; + } + + public SessionManager get(String sessionId) { + SessionProperties sessionProperties = this.sessionStorage.getSessionProperties(sessionId); + return this.get(sessionProperties.mediaMode()); + } + +} From 8a440528ac3945dc8b832779094d95d89e312381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Jou=C3=9Fen?= Date: Mon, 9 Jul 2018 15:51:26 +0200 Subject: [PATCH 6/9] Add Bean for SessionManagerProvider in OpenViduServer --- .../src/main/java/io/openvidu/server/OpenViduServer.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java index 65fdc05692..a88079f3b4 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java +++ b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java @@ -25,6 +25,7 @@ import javax.annotation.PostConstruct; import javax.ws.rs.ProcessingException; +import io.openvidu.server.core.SessionManagerProvider; import io.openvidu.server.core.SessionStorage; import io.openvidu.server.core.Utils; import org.kurento.jsonrpc.JsonUtils; @@ -163,6 +164,10 @@ public CoturnCredentialsService coturnCredentialsService() { @ConditionalOnMissingBean public Utils utils() { return new Utils(); } + @Bean + @ConditionalOnMissingBean + public SessionManagerProvider sessionManagerProvider() { return new SessionManagerProvider(); } + @Override public void registerJsonRpcHandlers(JsonRpcHandlerRegistry registry) { registry.addHandler(rpcHandler().withPingWatchdog(true), "/openvidu"); From 5be0d7c6601383c13c0281a1460852f45af8ea90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Jou=C3=9Fen?= Date: Mon, 9 Jul 2018 16:53:02 +0200 Subject: [PATCH 7/9] Add putSessionPropertiesIfAbsent to SessionStorage --- .../src/main/java/io/openvidu/server/core/SessionStorage.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java index a0817f397e..b9a708bb37 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java @@ -63,6 +63,10 @@ public Collection getSessionObjects() { public SessionProperties getSessionProperties(String sessionId) { return this.sessionProperties.get(sessionId); } + public SessionProperties putSessionPropertiesIfAbsent(String sessionId, SessionProperties sessionProperties) { + return this.sessionProperties.putIfAbsent(sessionId, sessionProperties); + } + /** * Returns all the participants inside a session. * From 32329e117787b0b94db3666b51557d08abe4c3a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Jou=C3=9Fen?= Date: Mon, 9 Jul 2018 16:54:30 +0200 Subject: [PATCH 8/9] Put SessionProperties into Storage if a new session is created in the KurentoSessionManager --- .../io/openvidu/server/kurento/core/KurentoSessionManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index 6e01263d4d..3dd0126261 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -447,6 +447,7 @@ public void createSession(KurentoClientSessionInfo kcSessionInfo, SessionPropert kcProvider.destroyWhenUnused(), this.CDR, this.openviduConfig); KurentoSession oldSession = (KurentoSession) this.sessionStorage.putSessionIfAbsent(sessionId, session); + this.sessionStorage.putSessionPropertiesIfAbsent(sessionId, sessionProperties); if (oldSession != null) { log.warn("Session '{}' has just been created by another thread", sessionId); return; From 798a7b7e648b620dc90bced96e7e38dc00371a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Jou=C3=9Fen?= Date: Mon, 9 Jul 2018 16:55:06 +0200 Subject: [PATCH 9/9] Replace usages of SessionManager with usages of Utils, SessionStorage and SessionManagerProvider --- .../openvidu/server/core/SessionManager.java | 10 +-- .../openvidu/server/core/SessionStorage.java | 12 +++ .../server/rest/SessionRestController.java | 33 ++++---- .../io/openvidu/server/rpc/RpcHandler.java | 81 ++++++++++--------- 4 files changed, 75 insertions(+), 61 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index 124e1ce76a..e41643bd87 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -189,15 +189,7 @@ public boolean isPublisherInSession(String sessionId, Participant participant) { } public boolean isModeratorInSession(String sessionId, Participant participant) { - if (!this.isInsecureParticipant(participant.getParticipantPrivateId())) { - if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - return ParticipantRole.MODERATOR.equals(participant.getToken().getRole()); - } else { - return false; - } - } else { - return true; - } + return this.sessionStorage.isModeratorInSession(sessionId, participant); } public boolean isInsecureParticipant(String participantPrivateId) { diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java index b9a708bb37..6284ebd723 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionStorage.java @@ -308,4 +308,16 @@ public void showInsecureParticipants() { public void showAllParticipants() { log.info(": {}", this.sessionidParticipantpublicidParticipant.toString()); } + + public boolean isModeratorInSession(String sessionId, Participant participant) { + if (!this.isInsecureParticipant(participant.getParticipantPrivateId())) { + if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { + return ParticipantRole.MODERATOR.equals(participant.getToken().getRole()); + } else { + return false; + } + } else { + return true; + } + } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 17c74a87a3..67dd669924 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -57,11 +57,14 @@ public class SessionRestController { @Autowired - private SessionManager sessionManager; + private SessionManagerProvider sessionManagerProvider; @Autowired private SessionStorage sessionStorage; + @Autowired + private Utils utils; + @Autowired private ComposedRecordingService recordingService; @@ -125,11 +128,11 @@ public ResponseEntity getSessionId(@RequestBody(required = false) Ma } sessionId = customSessionId; } else { - sessionId = sessionManager.generateRandomChain(); + sessionId = utils.generateRandomChain(); this.sessionStorage.putTokenObject(sessionId, new ConcurrentHashMap<>()); } - sessionManager.storeSessionId(sessionId, sessionProperties); + sessionStorage.storeSessionId(sessionId, sessionProperties); JSONObject responseJson = new JSONObject(); responseJson.put("id", sessionId); @@ -140,7 +143,7 @@ public ResponseEntity getSessionId(@RequestBody(required = false) Ma @RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.GET) public ResponseEntity getSession(@PathVariable("sessionId") String sessionId, @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { - Session session = this.sessionManager.getSession(sessionId); + Session session = this.sessionStorage.getSession(sessionId); if (session != null) { JSONObject response = (webRtcStats == true) ? session.withStatsToJSON() : session.toJSON(); response.put("recording", this.recordingService.sessionIsBeingRecorded(sessionId)); @@ -154,7 +157,7 @@ public ResponseEntity getSession(@PathVariable("sessionId") String s @RequestMapping(value = "/sessions", method = RequestMethod.GET) public ResponseEntity listSessions( @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { - Collection sessions = this.sessionManager.getSessionObjects(); + Collection sessions = this.sessionStorage.getSessionObjects(); JSONObject json = new JSONObject(); JSONArray jsonArray = new JSONArray(); sessions.forEach(s -> { @@ -169,9 +172,9 @@ public ResponseEntity listSessions( @RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.DELETE) public ResponseEntity closeSession(@PathVariable("sessionId") String sessionId) { - Session session = this.sessionManager.getSession(sessionId); + Session session = this.sessionStorage.getSession(sessionId); if (session != null) { - this.sessionManager.closeSession(sessionId, "sessionClosedByServer"); + this.sessionManagerProvider.get(sessionId).closeSession(sessionId, "sessionClosedByServer"); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -181,11 +184,11 @@ public ResponseEntity closeSession(@PathVariable("sessionId") String @RequestMapping(value = "/sessions/{sessionId}/connection/{connectionId}", method = RequestMethod.DELETE) public ResponseEntity disconnectParticipant(@PathVariable("sessionId") String sessionId, @PathVariable("connectionId") String participantPublicId) { - Session session = this.sessionManager.getSession(sessionId); + Session session = this.sessionStorage.getSession(sessionId); if (session != null) { Participant participant = session.getParticipantByPublicId(participantPublicId); if (participant != null) { - this.sessionManager.evictParticipant(participant, null, null, "forceDisconnectByServer"); + this.sessionManagerProvider.get(sessionId).evictParticipant(participant, null, null, "forceDisconnectByServer"); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -198,9 +201,9 @@ public ResponseEntity disconnectParticipant(@PathVariable("sessionId @RequestMapping(value = "/sessions/{sessionId}/stream/{streamId}", method = RequestMethod.DELETE) public ResponseEntity unpublishStream(@PathVariable("sessionId") String sessionId, @PathVariable("streamId") String streamId) { - Session session = this.sessionManager.getSession(sessionId); + Session session = this.sessionStorage.getSession(sessionId); if (session != null) { - if (this.sessionManager.unpublishStream(session, streamId, null, null, "forceUnpublishByServer")) { + if (this.sessionManagerProvider.get(sessionId).unpublishStream(session, streamId, null, null, "forceUnpublishByServer")) { return new ResponseEntity<>(HttpStatus.NO_CONTENT); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -236,7 +239,7 @@ public ResponseEntity newToken(@RequestBody Map params) { metadata = (metadata != null) ? metadata : ""; - String token = sessionManager.newToken(sessionId, role, metadata); + String token = sessionStorage.newToken(sessionId, role, metadata); JSONObject responseJson = new JSONObject(); responseJson.put("id", token); responseJson.put("session", sessionId); @@ -271,7 +274,7 @@ public ResponseEntity startRecordingSession(@RequestBody Map p return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } - Session session = sessionManager.getSession(sessionId); + Session session = sessionStorage.getSession(sessionId); if (session == null) { // Session does not exist @@ -327,11 +330,11 @@ public ResponseEntity stopRecordingSession(@PathVariable("recordingI return new ResponseEntity<>(HttpStatus.CONFLICT); } - Session session = sessionManager.getSession(recording.getSessionId()); + Session session = sessionStorage.getSession(recording.getSessionId()); Recording stoppedRecording = this.recordingService.stopRecording(session); - sessionManager.evictParticipant( + sessionManagerProvider.get(session.getSessionId()).evictParticipant( session.getParticipantByPublicId(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID), null, null, "EVICT_RECORDER"); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java index 0382dd6041..5e70da097d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java @@ -22,6 +22,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import io.openvidu.java.client.MediaMode; +import io.openvidu.server.core.*; import org.kurento.jsonrpc.DefaultJsonRpcHandler; import org.kurento.jsonrpc.Session; import org.kurento.jsonrpc.Transaction; @@ -37,10 +39,6 @@ import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; import io.openvidu.server.config.OpenviduConfig; -import io.openvidu.server.core.MediaOptions; -import io.openvidu.server.core.Participant; -import io.openvidu.server.core.SessionManager; -import io.openvidu.server.core.Token; public class RpcHandler extends DefaultJsonRpcHandler { @@ -48,9 +46,14 @@ public class RpcHandler extends DefaultJsonRpcHandler { @Autowired OpenviduConfig openviduConfig; + @Autowired + SessionManagerProvider sessionManagerProvider; + + @Autowired + SessionStorage sessionStorage; @Autowired - SessionManager sessionManager; + Utils utils; @Autowired RpcNotificationService notificationService; @@ -155,32 +158,33 @@ public void joinRoom(RpcConnection rpcConnection, Request request) { boolean generateRecorderParticipant = false; if (openviduConfig.isOpenViduSecret(secret)) { - sessionManager.newInsecureParticipant(participantPrivatetId); - token = sessionManager.generateRandomChain(); + sessionStorage.newInsecureParticipant(participantPrivatetId); + token = utils.generateRandomChain(); if (recorder) { generateRecorderParticipant = true; } } - if (sessionManager.isTokenValidInSession(token, sessionId, participantPrivatetId)) { + if (sessionStorage.isTokenValidInSession(token, sessionId, participantPrivatetId)) { String clientMetadata = getStringParam(request, ProtocolElements.JOINROOM_METADATA_PARAM); - if (sessionManager.isMetadataFormatCorrect(clientMetadata)) { + if (utils.isMetadataFormatCorrect(clientMetadata)) { - Token tokenObj = sessionManager.consumeToken(sessionId, participantPrivatetId, token); + Token tokenObj = sessionStorage.consumeToken(sessionId, participantPrivatetId, token); Participant participant; if (generateRecorderParticipant) { - participant = sessionManager.newRecorderParticipant(sessionId, participantPrivatetId, tokenObj, + participant = sessionStorage.newRecorderParticipant(sessionId, participantPrivatetId, tokenObj, clientMetadata); } else { - participant = sessionManager.newParticipant(sessionId, participantPrivatetId, tokenObj, + participant = sessionStorage.newParticipant(sessionId, participantPrivatetId, tokenObj, clientMetadata); } rpcConnection.setSessionId(sessionId); - sessionManager.joinRoom(participant, sessionId, request.getId()); + //@TODO The MediaMode should be transmitted on joinRoom action to support different MediaMode. + sessionManagerProvider.get(MediaMode.ROUTED).joinRoom(participant, sessionId, request.getId()); } else { log.error("ERROR: Metadata format set in client-side is incorrect"); @@ -202,7 +206,7 @@ private void leaveRoom(RpcConnection rpcConnection, Request request) return; } - sessionManager.leaveRoom(participant, request.getId(), "disconnect", true); + sessionManagerProvider.get(rpcConnection.getSessionId()).leaveRoom(participant, request.getId(), "disconnect", true); log.info("Participant {} has left session {}", participant.getParticipantPublicId(), rpcConnection.getSessionId()); } @@ -215,9 +219,11 @@ private void publishVideo(RpcConnection rpcConnection, Request reque return; } - if (sessionManager.isPublisherInSession(rpcConnection.getSessionId(), participant)) { - MediaOptions options = sessionManager.generateMediaOptions(request); - sessionManager.publishVideo(participant, options, request.getId()); + String sessionId = rpcConnection.getSessionId(); + + if (sessionStorage.isPublisherInSession(sessionId, participant)) { + MediaOptions options = sessionManagerProvider.get(sessionId).generateMediaOptions(request); + sessionManagerProvider.get(sessionId).publishVideo(participant, options, request.getId()); } else { log.error("Error: participant {} is not a publisher", participant.getParticipantPublicId()); throw new OpenViduException(Code.USER_UNAUTHORIZED_ERROR_CODE, @@ -237,7 +243,7 @@ private void receiveVideoFrom(RpcConnection rpcConnection, Request r senderName = senderName.substring(0, senderName.indexOf("_")); String sdpOffer = getStringParam(request, ProtocolElements.RECEIVEVIDEO_SDPOFFER_PARAM); - sessionManager.subscribe(participant, senderName, sdpOffer, request.getId()); + sessionManagerProvider.get(rpcConnection.getSessionId()).subscribe(participant, senderName, sdpOffer, request.getId()); } private void unsubscribeFromVideo(RpcConnection rpcConnection, Request request) { @@ -249,7 +255,7 @@ private void unsubscribeFromVideo(RpcConnection rpcConnection, Request request) { @@ -265,7 +271,7 @@ private void onIceCandidate(RpcConnection rpcConnection, Request req String sdpMid = getStringParam(request, ProtocolElements.ONICECANDIDATE_SDPMIDPARAM); int sdpMLineIndex = getIntParam(request, ProtocolElements.ONICECANDIDATE_SDPMLINEINDEX_PARAM); - sessionManager.onIceCandidate(participant, endpointName, candidate, sdpMLineIndex, sdpMid, request.getId()); + sessionManagerProvider.get(rpcConnection.getSessionId()).onIceCandidate(participant, endpointName, candidate, sdpMLineIndex, sdpMid, request.getId()); } private void sendMessage(RpcConnection rpcConnection, Request request) { @@ -277,7 +283,7 @@ private void sendMessage(RpcConnection rpcConnection, Request reques } String message = getStringParam(request, ProtocolElements.SENDMESSAGE_MESSAGE_PARAM); - sessionManager.sendMessage(participant, message, request.getId()); + sessionManagerProvider.get(rpcConnection.getSessionId()).sendMessage(participant, message, request.getId()); } private void unpublishVideo(RpcConnection rpcConnection, Request request) { @@ -288,7 +294,7 @@ private void unpublishVideo(RpcConnection rpcConnection, Request req return; } - sessionManager.unpublishVideo(participant, null, request.getId(), "unpublish"); + sessionManagerProvider.get(rpcConnection.getSessionId()).unpublishVideo(participant, null, request.getId(), "unpublish"); } private void forceDisconnect(RpcConnection rpcConnection, Request request) { @@ -299,10 +305,10 @@ private void forceDisconnect(RpcConnection rpcConnection, Request re return; } - if (sessionManager.isModeratorInSession(rpcConnection.getSessionId(), participant)) { + if (sessionStorage.isModeratorInSession(rpcConnection.getSessionId(), participant)) { String connectionId = getStringParam(request, ProtocolElements.FORCEDISCONNECT_CONNECTIONID_PARAM); - sessionManager.evictParticipant( - sessionManager.getSession(rpcConnection.getSessionId()).getParticipantByPublicId(connectionId), + sessionManagerProvider.get(rpcConnection.getSessionId()).evictParticipant( + sessionStorage.getSession(rpcConnection.getSessionId()).getParticipantByPublicId(connectionId), participant, request.getId(), "forceDisconnectByUser"); } else { log.error("Error: participant {} is not a moderator", participant.getParticipantPublicId()); @@ -319,9 +325,9 @@ private void forceUnpublish(RpcConnection rpcConnection, Request req return; } - if (sessionManager.isModeratorInSession(rpcConnection.getSessionId(), participant)) { + if (sessionStorage.isModeratorInSession(rpcConnection.getSessionId(), participant)) { String streamId = getStringParam(request, ProtocolElements.FORCEUNPUBLISH_STREAMID_PARAM); - sessionManager.unpublishStream(sessionManager.getSession(rpcConnection.getSessionId()), streamId, + sessionManagerProvider.get(rpcConnection.getSessionId()).unpublishStream(sessionStorage.getSession(rpcConnection.getSessionId()), streamId, participant, request.getId(), "forceUnpublishByUser"); } else { log.error("Error: participant {} is not a moderator", participant.getParticipantPublicId()); @@ -344,12 +350,13 @@ private void streamPropertyChanged(RpcConnection rpcConnection, Request