mirror of https://github.com/OpenVidu/openvidu.git
Merge 798a7b7e64
into ccd8d7a8b9
commit
7da1495447
|
@ -25,6 +25,9 @@ import java.util.List;
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.ws.rs.ProcessingException;
|
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;
|
import org.kurento.jsonrpc.JsonUtils;
|
||||||
import org.kurento.jsonrpc.internal.server.config.JsonRpcConfiguration;
|
import org.kurento.jsonrpc.internal.server.config.JsonRpcConfiguration;
|
||||||
import org.kurento.jsonrpc.server.JsonRpcConfigurer;
|
import org.kurento.jsonrpc.server.JsonRpcConfigurer;
|
||||||
|
@ -154,6 +157,18 @@ public class OpenViduServer implements JsonRpcConfigurer {
|
||||||
return new CoturnCredentialsServiceFactory(openviduConfig()).getCoturnCredentialsService();
|
return new CoturnCredentialsServiceFactory(openviduConfig()).getCoturnCredentialsService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public SessionStorage sessionStorage() { return new SessionStorage(); }
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public Utils utils() { return new Utils(); }
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public SessionManagerProvider sessionManagerProvider() { return new SessionManagerProvider(); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerJsonRpcHandlers(JsonRpcHandlerRegistry registry) {
|
public void registerJsonRpcHandlers(JsonRpcHandlerRegistry registry) {
|
||||||
registry.addHandler(rpcHandler().withPingWatchdog(true), "/openvidu");
|
registry.addHandler(rpcHandler().withPingWatchdog(true), "/openvidu");
|
||||||
|
|
|
@ -64,11 +64,8 @@ public abstract class SessionManager {
|
||||||
@Autowired
|
@Autowired
|
||||||
protected CoturnCredentialsService coturnCredentialsService;
|
protected CoturnCredentialsService coturnCredentialsService;
|
||||||
|
|
||||||
protected ConcurrentMap<String, Session> sessions = new ConcurrentHashMap<>();
|
@Autowired
|
||||||
protected ConcurrentMap<String, SessionProperties> sessionProperties = new ConcurrentHashMap<>();
|
protected SessionStorage sessionStorage;
|
||||||
protected ConcurrentMap<String, ConcurrentHashMap<String, Participant>> sessionidParticipantpublicidParticipant = new ConcurrentHashMap<>();
|
|
||||||
protected ConcurrentMap<String, Boolean> insecureUsers = new ConcurrentHashMap<>();
|
|
||||||
public ConcurrentMap<String, ConcurrentHashMap<String, Token>> sessionidTokenTokenobj = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private volatile boolean closed = false;
|
private volatile boolean closed = false;
|
||||||
|
|
||||||
|
@ -104,7 +101,7 @@ public abstract class SessionManager {
|
||||||
* @return Session
|
* @return Session
|
||||||
*/
|
*/
|
||||||
public Session getSession(String sessionId) {
|
public Session getSession(String sessionId) {
|
||||||
return sessions.get(sessionId);
|
return this.sessionStorage.getSession(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,7 +110,7 @@ public abstract class SessionManager {
|
||||||
* @return set of the session's identifiers
|
* @return set of the session's identifiers
|
||||||
*/
|
*/
|
||||||
public Set<String> getSessions() {
|
public Set<String> getSessions() {
|
||||||
return new HashSet<String>(sessions.keySet());
|
return this.sessionStorage.getSessions();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -122,7 +119,7 @@ public abstract class SessionManager {
|
||||||
* @return set of the session's identifiers
|
* @return set of the session's identifiers
|
||||||
*/
|
*/
|
||||||
public Collection<Session> getSessionObjects() {
|
public Collection<Session> getSessionObjects() {
|
||||||
return sessions.values();
|
return this.sessionStorage.getSessionObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -135,13 +132,7 @@ public abstract class SessionManager {
|
||||||
* in case the session doesn't exist
|
* in case the session doesn't exist
|
||||||
*/
|
*/
|
||||||
public Set<Participant> getParticipants(String sessionId) throws OpenViduException {
|
public Set<Participant> getParticipants(String sessionId) throws OpenViduException {
|
||||||
Session session = sessions.get(sessionId);
|
return this.sessionStorage.getParticipants(sessionId);
|
||||||
if (session == null) {
|
|
||||||
throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId + "' not found");
|
|
||||||
}
|
|
||||||
Set<Participant> participants = session.getParticipants();
|
|
||||||
participants.removeIf(p -> p.isClosed());
|
|
||||||
return participants;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,16 +148,7 @@ public abstract class SessionManager {
|
||||||
* belong to it
|
* belong to it
|
||||||
*/
|
*/
|
||||||
public Participant getParticipant(String sessionId, String participantPrivateId) throws OpenViduException {
|
public Participant getParticipant(String sessionId, String participantPrivateId) throws OpenViduException {
|
||||||
Session session = sessions.get(sessionId);
|
return this.sessionStorage.getParticipant(sessionId, participantPrivateId);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -179,15 +161,7 @@ public abstract class SessionManager {
|
||||||
* in case the participant doesn't exist
|
* in case the participant doesn't exist
|
||||||
*/
|
*/
|
||||||
public Participant getParticipant(String participantPrivateId) throws OpenViduException {
|
public Participant getParticipant(String participantPrivateId) throws OpenViduException {
|
||||||
for (Session session : sessions.values()) {
|
return this.sessionStorage.getParticipant(participantPrivateId);
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MediaOptions generateMediaOptions(Request<JsonObject> request) {
|
public MediaOptions generateMediaOptions(Request<JsonObject> request) {
|
||||||
|
@ -195,108 +169,31 @@ public abstract class SessionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeSessionId(String sessionId, SessionProperties sessionProperties) {
|
public void storeSessionId(String sessionId, SessionProperties sessionProperties) {
|
||||||
this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
this.sessionStorage.storeSessionId(sessionId, sessionProperties);
|
||||||
this.sessionProperties.putIfAbsent(sessionId, sessionProperties);
|
|
||||||
showTokens();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String newToken(String sessionId, ParticipantRole role, String serverMetadata) throws OpenViduException {
|
public String newToken(String sessionId, ParticipantRole role, String serverMetadata) throws OpenViduException {
|
||||||
|
return this.sessionStorage.newToken(sessionId, role, serverMetadata);
|
||||||
ConcurrentHashMap<String, Token> 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTokenValidInSession(String token, String sessionId, String participanPrivatetId) {
|
public boolean isTokenValidInSession(String token, String sessionId, String participanPrivatetId) {
|
||||||
if (!this.isInsecureParticipant(participanPrivatetId)) {
|
return this.sessionStorage.isTokenValidInSession(token, sessionId, 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) {
|
public boolean isParticipantInSession(String sessionId, Participant participant) {
|
||||||
Session session = this.sessions.get(sessionId);
|
return this.sessionStorage.isParticipantInSession(sessionId, participant);
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPublisherInSession(String sessionId, Participant participant) {
|
public boolean isPublisherInSession(String sessionId, Participant participant) {
|
||||||
if (!this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
return this.sessionStorage.isPublisherInSession(sessionId, participant);
|
||||||
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 isModeratorInSession(String sessionId, Participant participant) {
|
public boolean isModeratorInSession(String sessionId, Participant participant) {
|
||||||
if (!this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
return this.sessionStorage.isModeratorInSession(sessionId, participant);
|
||||||
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
|
||||||
return ParticipantRole.MODERATOR.equals(participant.getToken().getRole());
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInsecureParticipant(String participantPrivateId) {
|
public boolean isInsecureParticipant(String participantPrivateId) {
|
||||||
if (this.insecureUsers.containsKey(participantPrivateId)) {
|
return this.sessionStorage.isInsecureParticipant(participantPrivateId);
|
||||||
log.info("The user with private id {} is an INSECURE user", participantPrivateId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMetadataFormatCorrect(String metadata) {
|
public boolean isMetadataFormatCorrect(String metadata) {
|
||||||
|
@ -305,62 +202,30 @@ public abstract class SessionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void newInsecureParticipant(String participantPrivateId) {
|
public void newInsecureParticipant(String participantPrivateId) {
|
||||||
this.insecureUsers.put(participantPrivateId, true);
|
this.sessionStorage.newInsecureParticipant(participantPrivateId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Participant newParticipant(String sessionId, String participantPrivatetId, Token token,
|
public Participant newParticipant(String sessionId, String participantPrivatetId, Token token,
|
||||||
String clientMetadata) {
|
String clientMetadata) {
|
||||||
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
return this.sessionStorage.newParticipant(sessionId, participantPrivatetId, token, clientMetadata);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Participant newRecorderParticipant(String sessionId, String participantPrivatetId, Token token,
|
public Participant newRecorderParticipant(String sessionId, String participantPrivatetId, Token token,
|
||||||
String clientMetadata) {
|
String clientMetadata) {
|
||||||
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
return this.sessionStorage.newRecorderParticipant(sessionId, participantPrivatetId, token, clientMetadata);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Token consumeToken(String sessionId, String participantPrivateId, String token) {
|
public Token consumeToken(String sessionId, String participantPrivateId, String token) {
|
||||||
if (this.sessionidTokenTokenobj.get(sessionId) != null) {
|
return this.sessionStorage.consumeToken(sessionId, participantPrivateId, token);
|
||||||
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() {
|
public void showTokens() { this.sessionStorage.showTokens(); }
|
||||||
log.info("<SESSIONID, TOKENS>: {}", this.sessionidTokenTokenobj.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showInsecureParticipants() {
|
public void showInsecureParticipants() {
|
||||||
log.info("<INSECURE_PARTICIPANTS>: {}", this.insecureUsers.toString());
|
this.sessionStorage.showInsecureParticipants();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showAllParticipants() {
|
public void showAllParticipants() { this.sessionStorage.showAllParticipants(); }
|
||||||
log.info("<SESSIONID, PARTICIPANTS>: {}", this.sessionidParticipantpublicidParticipant.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String generateRandomChain() {
|
public String generateRandomChain() {
|
||||||
return RandomStringUtils.randomAlphanumeric(16).toLowerCase();
|
return RandomStringUtils.randomAlphanumeric(16).toLowerCase();
|
||||||
|
@ -379,7 +244,7 @@ public abstract class SessionManager {
|
||||||
public void close() {
|
public void close() {
|
||||||
closed = true;
|
closed = true;
|
||||||
log.info("Closing all sessions");
|
log.info("Closing all sessions");
|
||||||
for (String sessionId : sessions.keySet()) {
|
for (String sessionId : this.sessionStorage.getSessions()) {
|
||||||
try {
|
try {
|
||||||
closeSession(sessionId, "openviduServerStopped");
|
closeSession(sessionId, "openviduServerStopped");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -405,7 +270,7 @@ public abstract class SessionManager {
|
||||||
* in case the session doesn't exist or has been already closed
|
* in case the session doesn't exist or has been already closed
|
||||||
*/
|
*/
|
||||||
public Set<Participant> closeSession(String sessionId, String reason) {
|
public Set<Participant> closeSession(String sessionId, String reason) {
|
||||||
Session session = sessions.get(sessionId);
|
Session session = this.sessionStorage.getSession(sessionId);
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId + "' not found");
|
throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId + "' not found");
|
||||||
}
|
}
|
||||||
|
@ -434,11 +299,7 @@ public abstract class SessionManager {
|
||||||
if (session.close(reason)) {
|
if (session.close(reason)) {
|
||||||
sessionEventsHandler.onSessionClosed(session.getSessionId(), reason);
|
sessionEventsHandler.onSessionClosed(session.getSessionId(), reason);
|
||||||
}
|
}
|
||||||
sessions.remove(session.getSessionId());
|
this.sessionStorage.emptyCollections(session);
|
||||||
|
|
||||||
sessionProperties.remove(session.getSessionId());
|
|
||||||
sessionidParticipantpublicidParticipant.remove(session.getSessionId());
|
|
||||||
sessionidTokenTokenobj.remove(session.getSessionId());
|
|
||||||
|
|
||||||
log.warn("Session '{}' removed and closed", session.getSessionId());
|
log.warn("Session '{}' removed and closed", session.getSessionId());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,323 @@
|
||||||
|
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<String, Session> sessions = new ConcurrentHashMap<>();
|
||||||
|
protected ConcurrentMap<String, SessionProperties> sessionProperties = new ConcurrentHashMap<>();
|
||||||
|
protected ConcurrentMap<String, ConcurrentHashMap<String, Participant>> sessionidParticipantpublicidParticipant = new ConcurrentHashMap<>();
|
||||||
|
protected ConcurrentMap<String, Boolean> insecureUsers = new ConcurrentHashMap<>();
|
||||||
|
protected ConcurrentMap<String, ConcurrentHashMap<String, Token>> 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<String> getSessions() {
|
||||||
|
return new HashSet<String>(sessions.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all currently active (opened) sessions.
|
||||||
|
*
|
||||||
|
* @return set of the session's identifiers
|
||||||
|
*/
|
||||||
|
public Collection<Session> 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); }
|
||||||
|
|
||||||
|
public SessionProperties putSessionPropertiesIfAbsent(String sessionId, SessionProperties sessionProperties) {
|
||||||
|
return this.sessionProperties.putIfAbsent(sessionId, sessionProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<Participant> 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<Participant> 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<String, Token> putTokenObject(String sessionId, ConcurrentHashMap<String, Token> map) {
|
||||||
|
return this.sessionidTokenTokenobj.putIfAbsent(sessionId, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTokenObject(String sessionId) {
|
||||||
|
this.sessionidTokenTokenobj.remove(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConcurrentHashMap<String, Token> getTokenObject(String sessionId) {
|
||||||
|
return this.sessionidTokenTokenobj.get(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String newToken(String sessionId, ParticipantRole role, String serverMetadata) throws OpenViduException {
|
||||||
|
ConcurrentHashMap<String, Token> 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<String, Participant> 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("<SESSIONID, TOKENS>: {}", this.sessionidTokenTokenobj.toString()); }
|
||||||
|
|
||||||
|
public void showInsecureParticipants() {
|
||||||
|
log.info("<INSECURE_PARTICIPANTS>: {}", this.insecureUsers.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showAllParticipants() {
|
||||||
|
log.info("<SESSIONID, PARTICIPANTS>: {}", 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -70,10 +70,10 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
|
|
||||||
KurentoClientSessionInfo kcSessionInfo = new OpenViduKurentoClientSessionInfo(
|
KurentoClientSessionInfo kcSessionInfo = new OpenViduKurentoClientSessionInfo(
|
||||||
participant.getParticipantPrivateId(), sessionId);
|
participant.getParticipantPrivateId(), sessionId);
|
||||||
KurentoSession session = (KurentoSession) sessions.get(sessionId);
|
KurentoSession session = (KurentoSession) this.sessionStorage.getSession(sessionId);
|
||||||
|
|
||||||
if (session == null && kcSessionInfo != null) {
|
if (session == null && kcSessionInfo != null) {
|
||||||
SessionProperties properties = sessionProperties.get(sessionId);
|
SessionProperties properties = this.sessionStorage.getSessionProperties(sessionId);
|
||||||
if (properties == null && this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
if (properties == null && this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
||||||
properties = new SessionProperties.Builder().mediaMode(MediaMode.ROUTED)
|
properties = new SessionProperties.Builder().mediaMode(MediaMode.ROUTED)
|
||||||
.recordingMode(RecordingMode.ALWAYS).defaultRecordingLayout(RecordingLayout.BEST_FIT)
|
.recordingMode(RecordingMode.ALWAYS).defaultRecordingLayout(RecordingLayout.BEST_FIT)
|
||||||
|
@ -81,7 +81,7 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
}
|
}
|
||||||
createSession(kcSessionInfo, properties);
|
createSession(kcSessionInfo, properties);
|
||||||
}
|
}
|
||||||
session = (KurentoSession) sessions.get(sessionId);
|
session = (KurentoSession) this.sessionStorage.getSession(sessionId);
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
log.warn("Session '{}' not found");
|
log.warn("Session '{}' not found");
|
||||||
throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId
|
throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "Session '" + sessionId
|
||||||
|
@ -125,26 +125,26 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
|
|
||||||
// Update control data structures
|
// Update control data structures
|
||||||
|
|
||||||
if (sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
if (this.sessionStorage.getPublicIdParticipantMap(sessionId) != null) {
|
||||||
Participant p = sessionidParticipantpublicidParticipant.get(sessionId)
|
Participant p = this.sessionStorage.getPublicIdParticipantMap(sessionId)
|
||||||
.remove(participant.getParticipantPublicId());
|
.remove(participant.getParticipantPublicId());
|
||||||
|
|
||||||
if (this.coturnCredentialsService.isCoturnAvailable()) {
|
if (this.coturnCredentialsService.isCoturnAvailable()) {
|
||||||
this.coturnCredentialsService.deleteUser(p.getToken().getTurnCredentials().getUsername());
|
this.coturnCredentialsService.deleteUser(p.getToken().getTurnCredentials().getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sessionidTokenTokenobj.get(sessionId) != null) {
|
if (this.sessionStorage.getTokenObject(sessionId) != null) {
|
||||||
sessionidTokenTokenobj.get(sessionId).remove(p.getToken().getToken());
|
this.sessionStorage.getTokenObject(sessionId).remove(p.getToken().getToken());
|
||||||
}
|
}
|
||||||
boolean stillParticipant = false;
|
boolean stillParticipant = false;
|
||||||
for (Session s : sessions.values()) {
|
for (Session s : this.sessionStorage.getSessionObjects()) {
|
||||||
if (s.getParticipantByPrivateId(p.getParticipantPrivateId()) != null) {
|
if (s.getParticipantByPrivateId(p.getParticipantPrivateId()) != null) {
|
||||||
stillParticipant = true;
|
stillParticipant = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!stillParticipant) {
|
if (!stillParticipant) {
|
||||||
insecureUsers.remove(p.getParticipantPrivateId());
|
this.sessionStorage.removeInsecureParticipant(p.getParticipantPrivateId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,7 +437,7 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
public void createSession(KurentoClientSessionInfo kcSessionInfo, SessionProperties sessionProperties)
|
public void createSession(KurentoClientSessionInfo kcSessionInfo, SessionProperties sessionProperties)
|
||||||
throws OpenViduException {
|
throws OpenViduException {
|
||||||
String sessionId = kcSessionInfo.getRoomName();
|
String sessionId = kcSessionInfo.getRoomName();
|
||||||
KurentoSession session = (KurentoSession) sessions.get(sessionId);
|
KurentoSession session = (KurentoSession) this.sessionStorage.getSession(sessionId);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
throw new OpenViduException(Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE,
|
throw new OpenViduException(Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE,
|
||||||
"Session '" + sessionId + "' already exists");
|
"Session '" + sessionId + "' already exists");
|
||||||
|
@ -446,7 +446,8 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
session = new KurentoSession(sessionId, sessionProperties, kurentoClient, kurentoSessionEventsHandler,
|
session = new KurentoSession(sessionId, sessionProperties, kurentoClient, kurentoSessionEventsHandler,
|
||||||
kcProvider.destroyWhenUnused(), this.CDR, this.openviduConfig);
|
kcProvider.destroyWhenUnused(), this.CDR, this.openviduConfig);
|
||||||
|
|
||||||
KurentoSession oldSession = (KurentoSession) sessions.putIfAbsent(sessionId, session);
|
KurentoSession oldSession = (KurentoSession) this.sessionStorage.putSessionIfAbsent(sessionId, session);
|
||||||
|
this.sessionStorage.putSessionPropertiesIfAbsent(sessionId, sessionProperties);
|
||||||
if (oldSession != null) {
|
if (oldSession != null) {
|
||||||
log.warn("Session '{}' has just been created by another thread", sessionId);
|
log.warn("Session '{}' has just been created by another thread", sessionId);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import io.openvidu.server.core.*;
|
||||||
import org.json.simple.JSONArray;
|
import org.json.simple.JSONArray;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -43,10 +44,6 @@ import io.openvidu.java.client.RecordingMode;
|
||||||
import io.openvidu.java.client.RecordingProperties;
|
import io.openvidu.java.client.RecordingProperties;
|
||||||
import io.openvidu.java.client.SessionProperties;
|
import io.openvidu.java.client.SessionProperties;
|
||||||
import io.openvidu.server.config.OpenviduConfig;
|
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.ComposedRecordingService;
|
||||||
import io.openvidu.server.recording.Recording;
|
import io.openvidu.server.recording.Recording;
|
||||||
|
|
||||||
|
@ -60,7 +57,13 @@ import io.openvidu.server.recording.Recording;
|
||||||
public class SessionRestController {
|
public class SessionRestController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SessionManager sessionManager;
|
private SessionManagerProvider sessionManagerProvider;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SessionStorage sessionStorage;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Utils utils;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ComposedRecordingService recordingService;
|
private ComposedRecordingService recordingService;
|
||||||
|
@ -120,16 +123,16 @@ public class SessionRestController {
|
||||||
|
|
||||||
String sessionId;
|
String sessionId;
|
||||||
if (customSessionId != null && !customSessionId.isEmpty()) {
|
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);
|
return new ResponseEntity<>(HttpStatus.CONFLICT);
|
||||||
}
|
}
|
||||||
sessionId = customSessionId;
|
sessionId = customSessionId;
|
||||||
} else {
|
} else {
|
||||||
sessionId = sessionManager.generateRandomChain();
|
sessionId = utils.generateRandomChain();
|
||||||
sessionManager.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
this.sessionStorage.putTokenObject(sessionId, new ConcurrentHashMap<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionManager.storeSessionId(sessionId, sessionProperties);
|
sessionStorage.storeSessionId(sessionId, sessionProperties);
|
||||||
JSONObject responseJson = new JSONObject();
|
JSONObject responseJson = new JSONObject();
|
||||||
responseJson.put("id", sessionId);
|
responseJson.put("id", sessionId);
|
||||||
|
|
||||||
|
@ -140,7 +143,7 @@ public class SessionRestController {
|
||||||
@RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.GET)
|
@RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.GET)
|
||||||
public ResponseEntity<JSONObject> getSession(@PathVariable("sessionId") String sessionId,
|
public ResponseEntity<JSONObject> getSession(@PathVariable("sessionId") String sessionId,
|
||||||
@RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) {
|
@RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) {
|
||||||
Session session = this.sessionManager.getSession(sessionId);
|
Session session = this.sessionStorage.getSession(sessionId);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
JSONObject response = (webRtcStats == true) ? session.withStatsToJSON() : session.toJSON();
|
JSONObject response = (webRtcStats == true) ? session.withStatsToJSON() : session.toJSON();
|
||||||
response.put("recording", this.recordingService.sessionIsBeingRecorded(sessionId));
|
response.put("recording", this.recordingService.sessionIsBeingRecorded(sessionId));
|
||||||
|
@ -154,7 +157,7 @@ public class SessionRestController {
|
||||||
@RequestMapping(value = "/sessions", method = RequestMethod.GET)
|
@RequestMapping(value = "/sessions", method = RequestMethod.GET)
|
||||||
public ResponseEntity<JSONObject> listSessions(
|
public ResponseEntity<JSONObject> listSessions(
|
||||||
@RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) {
|
@RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) {
|
||||||
Collection<Session> sessions = this.sessionManager.getSessionObjects();
|
Collection<Session> sessions = this.sessionStorage.getSessionObjects();
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
JSONArray jsonArray = new JSONArray();
|
JSONArray jsonArray = new JSONArray();
|
||||||
sessions.forEach(s -> {
|
sessions.forEach(s -> {
|
||||||
|
@ -169,9 +172,9 @@ public class SessionRestController {
|
||||||
|
|
||||||
@RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.DELETE)
|
@RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.DELETE)
|
||||||
public ResponseEntity<JSONObject> closeSession(@PathVariable("sessionId") String sessionId) {
|
public ResponseEntity<JSONObject> closeSession(@PathVariable("sessionId") String sessionId) {
|
||||||
Session session = this.sessionManager.getSession(sessionId);
|
Session session = this.sessionStorage.getSession(sessionId);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
this.sessionManager.closeSession(sessionId, "sessionClosedByServer");
|
this.sessionManagerProvider.get(sessionId).closeSession(sessionId, "sessionClosedByServer");
|
||||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||||
} else {
|
} else {
|
||||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
@ -181,11 +184,11 @@ public class SessionRestController {
|
||||||
@RequestMapping(value = "/sessions/{sessionId}/connection/{connectionId}", method = RequestMethod.DELETE)
|
@RequestMapping(value = "/sessions/{sessionId}/connection/{connectionId}", method = RequestMethod.DELETE)
|
||||||
public ResponseEntity<JSONObject> disconnectParticipant(@PathVariable("sessionId") String sessionId,
|
public ResponseEntity<JSONObject> disconnectParticipant(@PathVariable("sessionId") String sessionId,
|
||||||
@PathVariable("connectionId") String participantPublicId) {
|
@PathVariable("connectionId") String participantPublicId) {
|
||||||
Session session = this.sessionManager.getSession(sessionId);
|
Session session = this.sessionStorage.getSession(sessionId);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
Participant participant = session.getParticipantByPublicId(participantPublicId);
|
Participant participant = session.getParticipantByPublicId(participantPublicId);
|
||||||
if (participant != null) {
|
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);
|
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||||
} else {
|
} else {
|
||||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
@ -198,9 +201,9 @@ public class SessionRestController {
|
||||||
@RequestMapping(value = "/sessions/{sessionId}/stream/{streamId}", method = RequestMethod.DELETE)
|
@RequestMapping(value = "/sessions/{sessionId}/stream/{streamId}", method = RequestMethod.DELETE)
|
||||||
public ResponseEntity<JSONObject> unpublishStream(@PathVariable("sessionId") String sessionId,
|
public ResponseEntity<JSONObject> unpublishStream(@PathVariable("sessionId") String sessionId,
|
||||||
@PathVariable("streamId") String streamId) {
|
@PathVariable("streamId") String streamId) {
|
||||||
Session session = this.sessionManager.getSession(sessionId);
|
Session session = this.sessionStorage.getSession(sessionId);
|
||||||
if (session != null) {
|
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);
|
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||||
} else {
|
} else {
|
||||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
@ -236,7 +239,7 @@ public class SessionRestController {
|
||||||
|
|
||||||
metadata = (metadata != null) ? metadata : "";
|
metadata = (metadata != null) ? metadata : "";
|
||||||
|
|
||||||
String token = sessionManager.newToken(sessionId, role, metadata);
|
String token = sessionStorage.newToken(sessionId, role, metadata);
|
||||||
JSONObject responseJson = new JSONObject();
|
JSONObject responseJson = new JSONObject();
|
||||||
responseJson.put("id", token);
|
responseJson.put("id", token);
|
||||||
responseJson.put("session", sessionId);
|
responseJson.put("session", sessionId);
|
||||||
|
@ -271,7 +274,7 @@ public class SessionRestController {
|
||||||
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
|
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
Session session = sessionManager.getSession(sessionId);
|
Session session = sessionStorage.getSession(sessionId);
|
||||||
|
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
// Session does not exist
|
// Session does not exist
|
||||||
|
@ -327,11 +330,11 @@ public class SessionRestController {
|
||||||
return new ResponseEntity<>(HttpStatus.CONFLICT);
|
return new ResponseEntity<>(HttpStatus.CONFLICT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Session session = sessionManager.getSession(recording.getSessionId());
|
Session session = sessionStorage.getSession(recording.getSessionId());
|
||||||
|
|
||||||
Recording stoppedRecording = this.recordingService.stopRecording(session, "recordingStoppedByServer");
|
Recording stoppedRecording = this.recordingService.stopRecording(session, "recordingStoppedByServer");
|
||||||
|
|
||||||
sessionManager.evictParticipant(
|
sessionManagerProvider.get(session.getSessionId()).evictParticipant(
|
||||||
session.getParticipantByPublicId(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID), null, null,
|
session.getParticipantByPublicId(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID), null, null,
|
||||||
"EVICT_RECORDER");
|
"EVICT_RECORDER");
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
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.DefaultJsonRpcHandler;
|
||||||
import org.kurento.jsonrpc.Session;
|
import org.kurento.jsonrpc.Session;
|
||||||
import org.kurento.jsonrpc.Transaction;
|
import org.kurento.jsonrpc.Transaction;
|
||||||
|
@ -37,10 +39,6 @@ import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.client.internal.ProtocolElements;
|
import io.openvidu.client.internal.ProtocolElements;
|
||||||
import io.openvidu.server.config.OpenviduConfig;
|
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<JsonObject> {
|
public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
|
|
||||||
|
@ -48,9 +46,14 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
OpenviduConfig openviduConfig;
|
OpenviduConfig openviduConfig;
|
||||||
|
@Autowired
|
||||||
|
SessionManagerProvider sessionManagerProvider;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
SessionManager sessionManager;
|
SessionStorage sessionStorage;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
Utils utils;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
RpcNotificationService notificationService;
|
RpcNotificationService notificationService;
|
||||||
|
@ -155,32 +158,33 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
boolean generateRecorderParticipant = false;
|
boolean generateRecorderParticipant = false;
|
||||||
|
|
||||||
if (openviduConfig.isOpenViduSecret(secret)) {
|
if (openviduConfig.isOpenViduSecret(secret)) {
|
||||||
sessionManager.newInsecureParticipant(participantPrivatetId);
|
sessionStorage.newInsecureParticipant(participantPrivatetId);
|
||||||
token = sessionManager.generateRandomChain();
|
token = utils.generateRandomChain();
|
||||||
if (recorder) {
|
if (recorder) {
|
||||||
generateRecorderParticipant = true;
|
generateRecorderParticipant = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sessionManager.isTokenValidInSession(token, sessionId, participantPrivatetId)) {
|
if (sessionStorage.isTokenValidInSession(token, sessionId, participantPrivatetId)) {
|
||||||
|
|
||||||
String clientMetadata = getStringParam(request, ProtocolElements.JOINROOM_METADATA_PARAM);
|
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;
|
Participant participant;
|
||||||
|
|
||||||
if (generateRecorderParticipant) {
|
if (generateRecorderParticipant) {
|
||||||
participant = sessionManager.newRecorderParticipant(sessionId, participantPrivatetId, tokenObj,
|
participant = sessionStorage.newRecorderParticipant(sessionId, participantPrivatetId, tokenObj,
|
||||||
clientMetadata);
|
clientMetadata);
|
||||||
} else {
|
} else {
|
||||||
participant = sessionManager.newParticipant(sessionId, participantPrivatetId, tokenObj,
|
participant = sessionStorage.newParticipant(sessionId, participantPrivatetId, tokenObj,
|
||||||
clientMetadata);
|
clientMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcConnection.setSessionId(sessionId);
|
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 {
|
} else {
|
||||||
log.error("ERROR: Metadata format set in client-side is incorrect");
|
log.error("ERROR: Metadata format set in client-side is incorrect");
|
||||||
|
@ -202,7 +206,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
return;
|
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(),
|
log.info("Participant {} has left session {}", participant.getParticipantPublicId(),
|
||||||
rpcConnection.getSessionId());
|
rpcConnection.getSessionId());
|
||||||
}
|
}
|
||||||
|
@ -215,9 +219,11 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sessionManager.isPublisherInSession(rpcConnection.getSessionId(), participant)) {
|
String sessionId = rpcConnection.getSessionId();
|
||||||
MediaOptions options = sessionManager.generateMediaOptions(request);
|
|
||||||
sessionManager.publishVideo(participant, options, request.getId());
|
if (sessionStorage.isPublisherInSession(sessionId, participant)) {
|
||||||
|
MediaOptions options = sessionManagerProvider.get(sessionId).generateMediaOptions(request);
|
||||||
|
sessionManagerProvider.get(sessionId).publishVideo(participant, options, request.getId());
|
||||||
} else {
|
} else {
|
||||||
log.error("Error: participant {} is not a publisher", participant.getParticipantPublicId());
|
log.error("Error: participant {} is not a publisher", participant.getParticipantPublicId());
|
||||||
throw new OpenViduException(Code.USER_UNAUTHORIZED_ERROR_CODE,
|
throw new OpenViduException(Code.USER_UNAUTHORIZED_ERROR_CODE,
|
||||||
|
@ -237,7 +243,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
senderName = senderName.substring(0, senderName.indexOf("_"));
|
senderName = senderName.substring(0, senderName.indexOf("_"));
|
||||||
String sdpOffer = getStringParam(request, ProtocolElements.RECEIVEVIDEO_SDPOFFER_PARAM);
|
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<JsonObject> request) {
|
private void unsubscribeFromVideo(RpcConnection rpcConnection, Request<JsonObject> request) {
|
||||||
|
@ -249,7 +255,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
}
|
}
|
||||||
|
|
||||||
String senderName = getStringParam(request, ProtocolElements.UNSUBSCRIBEFROMVIDEO_SENDER_PARAM);
|
String senderName = getStringParam(request, ProtocolElements.UNSUBSCRIBEFROMVIDEO_SENDER_PARAM);
|
||||||
sessionManager.unsubscribe(participant, senderName, request.getId());
|
sessionManagerProvider.get(rpcConnection.getSessionId()).unsubscribe(participant, senderName, request.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onIceCandidate(RpcConnection rpcConnection, Request<JsonObject> request) {
|
private void onIceCandidate(RpcConnection rpcConnection, Request<JsonObject> request) {
|
||||||
|
@ -265,7 +271,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
String sdpMid = getStringParam(request, ProtocolElements.ONICECANDIDATE_SDPMIDPARAM);
|
String sdpMid = getStringParam(request, ProtocolElements.ONICECANDIDATE_SDPMIDPARAM);
|
||||||
int sdpMLineIndex = getIntParam(request, ProtocolElements.ONICECANDIDATE_SDPMLINEINDEX_PARAM);
|
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<JsonObject> request) {
|
private void sendMessage(RpcConnection rpcConnection, Request<JsonObject> request) {
|
||||||
|
@ -277,7 +283,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
}
|
}
|
||||||
|
|
||||||
String message = getStringParam(request, ProtocolElements.SENDMESSAGE_MESSAGE_PARAM);
|
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<JsonObject> request) {
|
private void unpublishVideo(RpcConnection rpcConnection, Request<JsonObject> request) {
|
||||||
|
@ -288,7 +294,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionManager.unpublishVideo(participant, null, request.getId(), "unpublish");
|
sessionManagerProvider.get(rpcConnection.getSessionId()).unpublishVideo(participant, null, request.getId(), "unpublish");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void forceDisconnect(RpcConnection rpcConnection, Request<JsonObject> request) {
|
private void forceDisconnect(RpcConnection rpcConnection, Request<JsonObject> request) {
|
||||||
|
@ -299,10 +305,10 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sessionManager.isModeratorInSession(rpcConnection.getSessionId(), participant)) {
|
if (sessionStorage.isModeratorInSession(rpcConnection.getSessionId(), participant)) {
|
||||||
String connectionId = getStringParam(request, ProtocolElements.FORCEDISCONNECT_CONNECTIONID_PARAM);
|
String connectionId = getStringParam(request, ProtocolElements.FORCEDISCONNECT_CONNECTIONID_PARAM);
|
||||||
sessionManager.evictParticipant(
|
sessionManagerProvider.get(rpcConnection.getSessionId()).evictParticipant(
|
||||||
sessionManager.getSession(rpcConnection.getSessionId()).getParticipantByPublicId(connectionId),
|
sessionStorage.getSession(rpcConnection.getSessionId()).getParticipantByPublicId(connectionId),
|
||||||
participant, request.getId(), "forceDisconnectByUser");
|
participant, request.getId(), "forceDisconnectByUser");
|
||||||
} else {
|
} else {
|
||||||
log.error("Error: participant {} is not a moderator", participant.getParticipantPublicId());
|
log.error("Error: participant {} is not a moderator", participant.getParticipantPublicId());
|
||||||
|
@ -319,9 +325,9 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sessionManager.isModeratorInSession(rpcConnection.getSessionId(), participant)) {
|
if (sessionStorage.isModeratorInSession(rpcConnection.getSessionId(), participant)) {
|
||||||
String streamId = getStringParam(request, ProtocolElements.FORCEUNPUBLISH_STREAMID_PARAM);
|
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");
|
participant, request.getId(), "forceUnpublishByUser");
|
||||||
} else {
|
} else {
|
||||||
log.error("Error: participant {} is not a moderator", participant.getParticipantPublicId());
|
log.error("Error: participant {} is not a moderator", participant.getParticipantPublicId());
|
||||||
|
@ -344,12 +350,13 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
JsonElement newValue = getParam(request, ProtocolElements.STREAMPROPERTYCHANGED_NEWVALUE_PARAM);
|
JsonElement newValue = getParam(request, ProtocolElements.STREAMPROPERTYCHANGED_NEWVALUE_PARAM);
|
||||||
String reason = getStringParam(request, ProtocolElements.STREAMPROPERTYCHANGED_REASON_PARAM);
|
String reason = getStringParam(request, ProtocolElements.STREAMPROPERTYCHANGED_REASON_PARAM);
|
||||||
|
|
||||||
sessionManager.streamPropertyChanged(participant, request.getId(), streamId, property, newValue, reason);
|
sessionManagerProvider.get(rpcConnection.getSessionId()).streamPropertyChanged(participant, request.getId(), streamId, property, newValue, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void leaveRoomAfterConnClosed(String participantPrivateId, String reason) {
|
public void leaveRoomAfterConnClosed(String sessionId, String participantPrivateId, String reason) {
|
||||||
try {
|
try {
|
||||||
sessionManager.evictParticipant(this.sessionManager.getParticipant(participantPrivateId), null, null,
|
SessionManager sessionManager = sessionManagerProvider.get(sessionId);
|
||||||
|
sessionManager.evictParticipant(sessionManager.getParticipant(participantPrivateId), null, null,
|
||||||
reason);
|
reason);
|
||||||
log.info("Evicted participant with privateId {}", participantPrivateId);
|
log.info("Evicted participant with privateId {}", participantPrivateId);
|
||||||
} catch (OpenViduException e) {
|
} catch (OpenViduException e) {
|
||||||
|
@ -374,7 +381,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
message = "Evicting participant with private id {} because of a network disconnection";
|
message = "Evicting participant with private id {} because of a network disconnection";
|
||||||
} else if (status == null) { // && this.webSocketBrokenPipeTransportError.remove(rpcSessionId) != null)) {
|
} else if (status == null) { // && this.webSocketBrokenPipeTransportError.remove(rpcSessionId) != null)) {
|
||||||
try {
|
try {
|
||||||
Participant p = sessionManager.getParticipant(rpcSession.getSessionId());
|
Participant p = sessionStorage.getParticipant(rpcSession.getSessionId());
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
message = "Evicting participant with private id {} because its websocket unexpectedly closed in the client side";
|
message = "Evicting participant with private id {} because its websocket unexpectedly closed in the client side";
|
||||||
}
|
}
|
||||||
|
@ -385,10 +392,10 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
if (!message.isEmpty()) {
|
if (!message.isEmpty()) {
|
||||||
RpcConnection rpc = this.notificationService.closeRpcSession(rpcSessionId);
|
RpcConnection rpc = this.notificationService.closeRpcSession(rpcSessionId);
|
||||||
if (rpc != null && rpc.getSessionId() != null) {
|
if (rpc != null && rpc.getSessionId() != null) {
|
||||||
io.openvidu.server.core.Session session = this.sessionManager.getSession(rpc.getSessionId());
|
io.openvidu.server.core.Session session = this.sessionStorage.getSession(rpc.getSessionId());
|
||||||
if (session != null && session.getParticipantByPrivateId(rpc.getParticipantPrivateId()) != null) {
|
if (session != null && session.getParticipantByPrivateId(rpc.getParticipantPrivateId()) != null) {
|
||||||
log.info(message, rpc.getParticipantPrivateId());
|
log.info(message, rpc.getParticipantPrivateId());
|
||||||
leaveRoomAfterConnClosed(rpc.getParticipantPrivateId(), "networkDisconnect");
|
leaveRoomAfterConnClosed(rpcSessionId, rpc.getParticipantPrivateId(), "networkDisconnect");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,7 +404,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
log.warn(
|
log.warn(
|
||||||
"Evicting participant with private id {} because a transport error took place and its web socket connection is now closed",
|
"Evicting participant with private id {} because a transport error took place and its web socket connection is now closed",
|
||||||
rpcSession.getSessionId());
|
rpcSession.getSessionId());
|
||||||
this.leaveRoomAfterConnClosed(rpcSessionId, "networkDisconnect");
|
this.leaveRoomAfterConnClosed(rpcSessionId, rpcSessionId, "networkDisconnect");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,11 +474,11 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
errorMsg = "No session information found for participant with privateId " + participantPrivateId
|
errorMsg = "No session information found for participant with privateId " + participantPrivateId
|
||||||
+ ". Using the admin method to evict the user.";
|
+ ". Using the admin method to evict the user.";
|
||||||
log.warn(errorMsg);
|
log.warn(errorMsg);
|
||||||
leaveRoomAfterConnClosed(participantPrivateId, "");
|
leaveRoomAfterConnClosed(sessionId, participantPrivateId, "");
|
||||||
throw new OpenViduException(Code.GENERIC_ERROR_CODE, errorMsg);
|
throw new OpenViduException(Code.GENERIC_ERROR_CODE, errorMsg);
|
||||||
} else {
|
} else {
|
||||||
// Sanity check: don't call RPC method unless the id checks out
|
// Sanity check: don't call RPC method unless the id checks out
|
||||||
Participant participant = sessionManager.getParticipant(sessionId, participantPrivateId);
|
Participant participant = sessionStorage.getParticipant(sessionId, participantPrivateId);
|
||||||
if (participant != null) {
|
if (participant != null) {
|
||||||
errorMsg = "Participant " + participant.getParticipantPublicId() + " is calling method '" + methodName
|
errorMsg = "Participant " + participant.getParticipantPublicId() + " is calling method '" + methodName
|
||||||
+ "' in session " + sessionId;
|
+ "' in session " + sessionId;
|
||||||
|
@ -481,7 +488,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
errorMsg = "Participant with private id " + participantPrivateId + " not found in session " + sessionId
|
errorMsg = "Participant with private id " + participantPrivateId + " not found in session " + sessionId
|
||||||
+ ". Using the admin method to evict the user.";
|
+ ". Using the admin method to evict the user.";
|
||||||
log.warn(errorMsg);
|
log.warn(errorMsg);
|
||||||
leaveRoomAfterConnClosed(participantPrivateId, "");
|
leaveRoomAfterConnClosed(sessionId, participantPrivateId, "");
|
||||||
throw new OpenViduException(Code.GENERIC_ERROR_CODE, errorMsg);
|
throw new OpenViduException(Code.GENERIC_ERROR_CODE, errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue