diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Session.java b/openvidu-server/src/main/java/io/openvidu/server/core/Session.java index 310feb0f..dfc4a9ba 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Session.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Session.java @@ -27,6 +27,9 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -42,9 +45,12 @@ import io.openvidu.server.recording.service.RecordingManager; public class Session implements SessionInterface { + private static final Logger log = LoggerFactory.getLogger(Session.class); + protected OpenviduConfig openviduConfig; protected RecordingManager recordingManager; + protected ConcurrentMap tokens = new ConcurrentHashMap<>(); protected final ConcurrentMap participants = new ConcurrentHashMap<>(); protected String sessionId; protected SessionProperties sessionProperties; @@ -72,6 +78,7 @@ public class Session implements SessionInterface { this.sessionProperties = previousSession.getSessionProperties(); this.openviduConfig = previousSession.openviduConfig; this.recordingManager = previousSession.recordingManager; + this.tokens = previousSession.tokens; } public Session(String sessionId, SessionProperties sessionProperties, OpenviduConfig openviduConfig, @@ -132,6 +139,24 @@ public class Session implements SessionInterface { this.activePublishers.decrementAndGet(); } + public void storeToken(Token token) { + this.tokens.put(token.getToken(), token); + } + + public boolean isTokenValid(String token) { + return this.tokens.containsKey(token); + } + + public Token consumeToken(String token) { + Token tokenObj = this.tokens.remove(token); + showTokens("Token consumed"); + return tokenObj; + } + + public void showTokens(String preMessage) { + log.info("{} { Session: {} | Tokens: {} }", preMessage, this.sessionId, this.tokens.keySet().toString()); + } + public boolean isClosed() { return closed; } 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 c62d5ffc..d13247f8 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 @@ -89,7 +89,6 @@ public abstract class SessionManager { protected ConcurrentMap> sessionidAccumulatedRecordings = new ConcurrentHashMap<>(); protected ConcurrentMap insecureUsers = new ConcurrentHashMap<>(); - public ConcurrentMap> sessionidTokenTokenobj = new ConcurrentHashMap<>(); public abstract void joinRoom(Participant participant, String sessionId, Integer transactionId); @@ -281,51 +280,29 @@ public abstract class SessionManager { final String sessionId = sessionNotActive.getSessionId(); this.sessionsNotActive.put(sessionId, sessionNotActive); this.initializeCollections(sessionId); - showTokens(); return sessionNotActive; } - public String newToken(String sessionId, OpenViduRole role, String serverMetadata, + public String newToken(Session session, OpenViduRole role, String serverMetadata, KurentoTokenOptions kurentoTokenOptions) throws OpenViduException { - - Map tokenMap = this.sessionidTokenTokenobj.get(sessionId); - - if (tokenMap != null) { - - if (!formatChecker.isServerMetadataFormatCorrect(serverMetadata)) { - log.error("Data invalid format"); - throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format"); - } - - Token token = tokenGenerator.generateToken(sessionId, role, serverMetadata, kurentoTokenOptions); - tokenMap.putIfAbsent(token.getToken(), token); - showTokens(); - return token.getToken(); - - } else { - log.error("sessionId [" + sessionId + "] was not found (race condition error)"); - throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "sessionId [" + sessionId + "] not found"); + if (!formatChecker.isServerMetadataFormatCorrect(serverMetadata)) { + log.error("Data invalid format"); + throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format"); } + Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), role, serverMetadata, + kurentoTokenOptions); + session.storeToken(tokenObj); + session.showTokens("Token created"); + return tokenObj.getToken(); } - public boolean isTokenValidInSession(String token, String sessionId, String participanPrivatetId, - String serverMetadata) { - if (!this.isInsecureParticipant(participanPrivatetId)) { - if (this.sessionidTokenTokenobj.get(sessionId) != null) { - return this.sessionidTokenTokenobj.get(sessionId).containsKey(token); - } else { - return false; - } - } else { - this.initializeCollections(sessionId); - this.sessionidTokenTokenobj.get(sessionId).putIfAbsent(token, - new Token(token, OpenViduRole.PUBLISHER, serverMetadata, - this.coturnCredentialsService.isCoturnAvailable() - ? this.coturnCredentialsService.createUser() - : null, - null)); - return true; - } + public Token newTokenForInsecureUser(Session session, String token, String serverMetadata) { + Token tokenObj = new Token(token, OpenViduRole.PUBLISHER, serverMetadata != null ? serverMetadata : "", + this.coturnCredentialsService.isCoturnAvailable() ? this.coturnCredentialsService.createUser() : null, + null); + session.storeToken(tokenObj); + session.showTokens("Token created for insecure user"); + return tokenObj; } public boolean isPublisherInSession(String sessionId, Participant participant) { @@ -416,23 +393,6 @@ public abstract class SessionManager { } } - 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); - } - } - - public void showTokens() { - log.info(": {}", this.sessionidTokenTokenobj.toString()); - } - /** * Closes all resources. This method has been annotated with the @PreDestroy * directive (javax.annotation package) so that it will be automatically called @@ -531,13 +491,11 @@ public abstract class SessionManager { sessionidParticipantpublicidParticipant.remove(sessionId); sessionidFinalUsers.remove(sessionId); sessionidAccumulatedRecordings.remove(sessionId); - sessionidTokenTokenobj.remove(sessionId); } private void initializeCollections(String sessionId) { this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>()); this.sessionidFinalUsers.putIfAbsent(sessionId, new ConcurrentHashMap<>()); - this.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>()); if (this.openviduConfig.isRecordingModuleEnabled()) { this.sessionidAccumulatedRecordings.putIfAbsent(sessionId, new ConcurrentLinkedQueue<>()); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java index a825952d..c48b982e 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java @@ -138,6 +138,8 @@ public class KurentoSession extends Session { public boolean close(EndReason reason) { if (!closed) { + this.tokens.clear(); + for (Participant participant : participants.values()) { ((KurentoParticipant) participant).releaseAllFilters(); ((KurentoParticipant) participant).close(reason, true, 0); 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 fe24680a..d87a19ac 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 @@ -170,9 +170,6 @@ public class KurentoSessionManager extends SessionManager { this.coturnCredentialsService.deleteUser(p.getToken().getTurnCredentials().getUsername()); } - if (sessionidTokenTokenobj.get(sessionId) != null) { - sessionidTokenTokenobj.get(sessionId).remove(p.getToken().getToken()); - } boolean stillParticipant = false; for (Session s : sessions.values()) { if (s.getParticipantByPrivateId(p.getParticipantPrivateId()) != null) { @@ -185,8 +182,6 @@ public class KurentoSessionManager extends SessionManager { } } - showTokens(); - // Close Session if no more participants Set remainingParticipants = null; @@ -222,7 +217,6 @@ public class KurentoSessionManager extends SessionManager { log.info("No more participants in session '{}', removing it and closing it", sessionId); this.closeSessionAndEmptyCollections(session, reason, true); sessionClosedByLastParticipant = true; - showTokens(); } finally { session.closingLock.writeLock().unlock(); } @@ -909,10 +903,9 @@ public class KurentoSessionManager extends SessionManager { this.newInsecureParticipant(rtspConnectionId); String token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(15); - Token tokenObj = null; - if (this.isTokenValidInSession(token, sessionId, rtspConnectionId, serverMetadata)) { - tokenObj = this.consumeToken(sessionId, rtspConnectionId, token); - } + this.newTokenForInsecureUser(session, token, serverMetadata); + final Token tokenObj = session.consumeToken(token); + Participant ipcamParticipant = this.newIpcamParticipant(sessionId, rtspConnectionId, tokenObj, location, mediaOptions.getTypeOfVideo()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java index 477704d3..01c81325 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java @@ -494,7 +494,6 @@ public class RecordingManager { log.info("Closing session {} after automatic stop of recording {}", session.getSessionId(), recordingId); sessionManager.closeSessionAndEmptyCollections(session, EndReason.automaticStop, true); - sessionManager.showTokens(); } else { // There are users connected, but no one is publishing session.closingLock.writeLock().unlock(); // We don't need the lock if session's not closing @@ -536,7 +535,6 @@ public class RecordingManager { "Ongoing recording of session {} was explicetly stopped within timeout for automatic recording stop. Closing session", session.getSessionId()); sessionManager.closeSessionAndEmptyCollections(session, reason, false); - sessionManager.showTokens(); } return cancelled; } finally { 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 9e40f29f..8e77aaa6 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 @@ -21,6 +21,7 @@ import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; import java.util.Map; +import java.util.stream.Collectors; import org.apache.commons.lang3.RandomStringUtils; import org.slf4j.Logger; @@ -165,6 +166,8 @@ public class SessionRestController { } Session sessionNotActive = sessionManager.storeSessionNotActive(sessionId, sessionProperties); + log.info("New session {} initialized {}", sessionId, this.sessionManager.getSessionsWithNotActive().stream() + .map(Session::getSessionId).collect(Collectors.toList()).toString()); JsonObject responseJson = new JsonObject(); responseJson.addProperty("id", sessionNotActive.getSessionId()); responseJson.addProperty("createdAt", sessionNotActive.getStartTime()); @@ -364,7 +367,7 @@ public class SessionRestController { // While closing a session tokens can't be generated if (session.closingLock.readLock().tryLock()) { try { - String token = sessionManager.newToken(sessionId, role, metadata, kurentoTokenOptions); + String token = sessionManager.newToken(session, role, metadata, kurentoTokenOptions); JsonObject responseJson = new JsonObject(); responseJson.addProperty("id", token); 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 0696aa1f..47358a1f 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 @@ -176,6 +176,13 @@ public class RpcHandler extends DefaultJsonRpcHandler { String platform = getStringParam(request, ProtocolElements.JOINROOM_PLATFORM_PARAM); String participantPrivatetId = rpcConnection.getParticipantPrivateId(); + final io.openvidu.server.core.Session session = sessionManager.getSessionWithNotActive(sessionId); + if (session == null) { + log.error("ERROR: Session {} not found", sessionId); + throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, + "Unable to join session. Session " + sessionId + " cannot be found"); + } + InetAddress remoteAddress = null; GeoLocation location = null; Object obj = rpcConnection.getSession().getAttributes().get("remoteAddress"); @@ -234,24 +241,25 @@ public class RpcHandler extends DefaultJsonRpcHandler { sessionManager.newInsecureParticipant(participantPrivatetId); token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(15); + sessionManager.newTokenForInsecureUser(session, token, null); if (recorder) { generateRecorderParticipant = true; } } - if (sessionManager.isTokenValidInSession(token, sessionId, participantPrivatetId, "")) { - + Token tokenObj = session.consumeToken(token); + if (tokenObj != null) { String clientMetadata = getStringParam(request, ProtocolElements.JOINROOM_METADATA_PARAM); - if (sessionManager.formatChecker.isServerMetadataFormatCorrect(clientMetadata)) { - Token tokenObj = sessionManager.consumeToken(sessionId, participantPrivatetId, token); - Participant participant; - io.openvidu.server.core.Session session = sessionManager.getSessionWithNotActive(sessionId); - // While closing a session users can't join if (session.closingLock.readLock().tryLock()) { + if (session.isClosed()) { + throw new OpenViduException(Code.ROOM_CLOSED_ERROR_CODE, + "Unable to join the session. Session " + sessionId + " is closed"); + } try { + Participant participant; if (generateRecorderParticipant) { participant = sessionManager.newRecorderParticipant(sessionId, participantPrivatetId, tokenObj, clientMetadata); @@ -276,13 +284,13 @@ public class RpcHandler extends DefaultJsonRpcHandler { } } else { log.error("ERROR: Metadata format set in client-side is incorrect"); - throw new OpenViduException(Code.USER_METADATA_FORMAT_INVALID_ERROR_CODE, - "Unable to join room. The metadata received from the client-side has an invalid format"); + throw new OpenViduException(Code.USER_METADATA_FORMAT_INVALID_ERROR_CODE, "Unable to join session " + + sessionId + ". The metadata received from the client-side has an invalid format"); } } else { - log.error("ERROR: sessionId or token not valid"); + log.error("ERROR: token not valid"); throw new OpenViduException(Code.USER_UNAUTHORIZED_ERROR_CODE, - "Unable to join room. The user is not authorized"); + "Unable to join session " + sessionId + ". Token " + token + "is not valid"); } }