mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: important refactoring (Session from interface to class)
parent
b2ec5ccb10
commit
1b47b9f2fa
|
@ -17,38 +17,162 @@
|
|||
|
||||
package io.openvidu.server.core;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import io.openvidu.client.OpenViduException;
|
||||
import io.openvidu.client.OpenViduException.Code;
|
||||
import io.openvidu.client.internal.ProtocolElements;
|
||||
import io.openvidu.java.client.Recording;
|
||||
import io.openvidu.java.client.RecordingLayout;
|
||||
import io.openvidu.java.client.SessionProperties;
|
||||
import io.openvidu.server.cdr.CallDetailRecord;
|
||||
import io.openvidu.server.config.OpenviduConfig;
|
||||
import io.openvidu.server.kurento.core.KurentoParticipant;
|
||||
import io.openvidu.server.recording.service.RecordingManager;
|
||||
|
||||
public interface Session {
|
||||
public class Session implements SessionInterface {
|
||||
|
||||
String getSessionId();
|
||||
protected OpenviduConfig openviduConfig;
|
||||
protected RecordingManager recordingManager;
|
||||
protected CallDetailRecord CDR;
|
||||
|
||||
SessionProperties getSessionProperties();
|
||||
protected final ConcurrentMap<String, Participant> participants = new ConcurrentHashMap<>();
|
||||
protected String sessionId;
|
||||
protected SessionProperties sessionProperties;
|
||||
protected Long startTime;
|
||||
|
||||
void join(Participant participant);
|
||||
protected volatile boolean closed = false;
|
||||
protected AtomicInteger activePublishers = new AtomicInteger(0);
|
||||
|
||||
void leave(String participantPrivateId, String reason);
|
||||
public Session(Session previousSession) {
|
||||
this.sessionId = previousSession.getSessionId();
|
||||
this.startTime = previousSession.getStartTime();
|
||||
this.sessionProperties = previousSession.getSessionProperties();
|
||||
this.CDR = previousSession.CDR;
|
||||
this.openviduConfig = previousSession.openviduConfig;
|
||||
this.recordingManager = previousSession.recordingManager;
|
||||
}
|
||||
|
||||
boolean close(String reason);
|
||||
public Session(String sessionId, SessionProperties sessionProperties, CallDetailRecord CDR,
|
||||
OpenviduConfig openviduConfig, RecordingManager recordingManager) {
|
||||
this.sessionId = sessionId;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.sessionProperties = sessionProperties;
|
||||
this.CDR = CDR;
|
||||
this.openviduConfig = openviduConfig;
|
||||
this.recordingManager = recordingManager;
|
||||
}
|
||||
|
||||
boolean isClosed();
|
||||
public String getSessionId() {
|
||||
return this.sessionId;
|
||||
}
|
||||
|
||||
Set<Participant> getParticipants();
|
||||
public SessionProperties getSessionProperties() {
|
||||
return this.sessionProperties;
|
||||
}
|
||||
|
||||
Participant getParticipantByPrivateId(String participantPrivateId);
|
||||
public Long getStartTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
Participant getParticipantByPublicId(String participantPublicId);
|
||||
public Set<Participant> getParticipants() {
|
||||
checkClosed();
|
||||
return new HashSet<Participant>(this.participants.values());
|
||||
}
|
||||
|
||||
int getActivePublishers();
|
||||
public Participant getParticipantByPrivateId(String participantPrivateId) {
|
||||
checkClosed();
|
||||
return participants.get(participantPrivateId);
|
||||
}
|
||||
|
||||
JsonObject toJson();
|
||||
public Participant getParticipantByPublicId(String participantPublicId) {
|
||||
checkClosed();
|
||||
for (Participant p : participants.values()) {
|
||||
if (p.getParticipantPublicId().equals(participantPublicId)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
JsonObject withStatsToJson();
|
||||
public int getActivePublishers() {
|
||||
return activePublishers.get();
|
||||
}
|
||||
|
||||
Long getStartTime();
|
||||
public void registerPublisher() {
|
||||
this.activePublishers.incrementAndGet();
|
||||
}
|
||||
|
||||
public void deregisterPublisher() {
|
||||
this.activePublishers.decrementAndGet();
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
protected void checkClosed() {
|
||||
if (isClosed()) {
|
||||
throw new OpenViduException(Code.ROOM_CLOSED_ERROR_CODE, "The session '" + sessionId + "' is closed");
|
||||
}
|
||||
}
|
||||
|
||||
public JsonObject toJson() {
|
||||
return this.sharedJson(KurentoParticipant::toJson);
|
||||
}
|
||||
|
||||
public JsonObject withStatsToJson() {
|
||||
return this.sharedJson(KurentoParticipant::withStatsToJson);
|
||||
}
|
||||
|
||||
private JsonObject sharedJson(Function<KurentoParticipant, JsonObject> toJsonFunction) {
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("sessionId", this.sessionId);
|
||||
json.addProperty("createdAt", this.startTime);
|
||||
json.addProperty("mediaMode", this.sessionProperties.mediaMode().name());
|
||||
json.addProperty("recordingMode", this.sessionProperties.recordingMode().name());
|
||||
json.addProperty("defaultOutputMode", this.sessionProperties.defaultOutputMode().name());
|
||||
if (Recording.OutputMode.COMPOSED.equals(this.sessionProperties.defaultOutputMode())) {
|
||||
json.addProperty("defaultRecordingLayout", this.sessionProperties.defaultRecordingLayout().name());
|
||||
if (RecordingLayout.CUSTOM.equals(this.sessionProperties.defaultRecordingLayout())) {
|
||||
json.addProperty("defaultCustomLayout", this.sessionProperties.defaultCustomLayout());
|
||||
}
|
||||
}
|
||||
if (this.sessionProperties.customSessionId() != null) {
|
||||
json.addProperty("customSessionId", this.sessionProperties.customSessionId());
|
||||
}
|
||||
JsonObject connections = new JsonObject();
|
||||
JsonArray participants = new JsonArray();
|
||||
this.participants.values().forEach(p -> {
|
||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(p.getParticipantPublicId())) {
|
||||
participants.add(toJsonFunction.apply((KurentoParticipant) p));
|
||||
}
|
||||
});
|
||||
connections.addProperty("numberOfElements", participants.size());
|
||||
connections.add("content", participants);
|
||||
json.add("connections", connections);
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void join(Participant participant) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leave(String participantPrivateId, String reason) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean close(String reason) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* (C) Copyright 2017-2019 OpenVidu (https://openvidu.io/)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package io.openvidu.server.core;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import io.openvidu.java.client.SessionProperties;
|
||||
|
||||
public interface SessionInterface {
|
||||
|
||||
String getSessionId();
|
||||
|
||||
SessionProperties getSessionProperties();
|
||||
|
||||
void join(Participant participant);
|
||||
|
||||
void leave(String participantPrivateId, String reason);
|
||||
|
||||
boolean close(String reason);
|
||||
|
||||
boolean isClosed();
|
||||
|
||||
Set<Participant> getParticipants();
|
||||
|
||||
Participant getParticipantByPrivateId(String participantPrivateId);
|
||||
|
||||
Participant getParticipantByPublicId(String participantPublicId);
|
||||
|
||||
int getActivePublishers();
|
||||
|
||||
JsonObject toJson();
|
||||
|
||||
JsonObject withStatsToJson();
|
||||
|
||||
Long getStartTime();
|
||||
|
||||
}
|
|
@ -22,6 +22,7 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
|
@ -69,9 +70,9 @@ public abstract class SessionManager {
|
|||
public FormatChecker formatChecker = new FormatChecker();
|
||||
|
||||
protected ConcurrentMap<String, Session> sessions = new ConcurrentHashMap<>();
|
||||
protected ConcurrentMap<String, SessionProperties> sessionProperties = new ConcurrentHashMap<>();
|
||||
protected ConcurrentMap<String, Long> sessionCreationTime = new ConcurrentHashMap<>();
|
||||
protected ConcurrentMap<String, Session> sessionsNotActive = new ConcurrentHashMap<>();
|
||||
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<>();
|
||||
|
||||
|
@ -137,17 +138,21 @@ public abstract class SessionManager {
|
|||
*
|
||||
* @return set of the session's identifiers
|
||||
*/
|
||||
public Set<String> getSessions() {
|
||||
return new HashSet<String>(sessions.keySet());
|
||||
public Collection<Session> getSessions() {
|
||||
return sessions.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all currently active (opened) sessions.
|
||||
*
|
||||
* @return set of the session's identifiers
|
||||
*/
|
||||
public Collection<Session> getSessionObjects() {
|
||||
return sessions.values();
|
||||
public Session getSessionNotActive(String sessionId) {
|
||||
return this.sessionsNotActive.get(sessionId);
|
||||
}
|
||||
|
||||
public Collection<Session> getSessionsWithNotActive() {
|
||||
Collection<Session> allSessions = new HashSet<>();
|
||||
allSessions.addAll(this.sessionsNotActive.values().stream()
|
||||
.filter(sessionNotActive -> !sessions.containsKey(sessionNotActive.getSessionId()))
|
||||
.collect(Collectors.toSet()));
|
||||
allSessions.addAll(this.getSessions());
|
||||
return allSessions;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -212,11 +217,12 @@ public abstract class SessionManager {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void storeSessionId(String sessionId, Long creationTime, SessionProperties sessionProperties) {
|
||||
public Session storeSessionNotActive(String sessionId, SessionProperties sessionProperties) {
|
||||
Session sessionNotActive = new Session(sessionId, sessionProperties, CDR, openviduConfig, recordingManager);
|
||||
this.sessionsNotActive.put(sessionId, sessionNotActive);
|
||||
this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
||||
this.sessionProperties.putIfAbsent(sessionId, sessionProperties);
|
||||
this.sessionCreationTime.putIfAbsent(sessionId, creationTime);
|
||||
showTokens();
|
||||
return sessionNotActive;
|
||||
}
|
||||
|
||||
public String newToken(String sessionId, ParticipantRole role, String serverMetadata,
|
||||
|
@ -254,7 +260,6 @@ public abstract class SessionManager {
|
|||
log.error("sessionId [" + sessionId + "] was not found");
|
||||
throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, "sessionId [" + sessionId + "] not found");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isTokenValidInSession(String token, String sessionId, String participanPrivatetId) {
|
||||
|
@ -266,7 +271,6 @@ public abstract class SessionManager {
|
|||
}
|
||||
} else {
|
||||
this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
||||
this.sessionCreationTime.putIfAbsent(sessionId, System.currentTimeMillis());
|
||||
this.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
||||
this.sessionidTokenTokenobj.get(sessionId).putIfAbsent(token,
|
||||
new Token(token, ParticipantRole.PUBLISHER, "",
|
||||
|
@ -278,15 +282,6 @@ public abstract class SessionManager {
|
|||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPublisherInSession(String sessionId, Participant participant) {
|
||||
if (!this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
||||
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
||||
|
@ -371,14 +366,6 @@ public abstract class SessionManager {
|
|||
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 String generateRandomChain() {
|
||||
return RandomStringUtils.randomAlphanumeric(16).toLowerCase();
|
||||
}
|
||||
|
@ -454,8 +441,7 @@ public abstract class SessionManager {
|
|||
}
|
||||
|
||||
sessions.remove(session.getSessionId());
|
||||
sessionProperties.remove(session.getSessionId());
|
||||
sessionCreationTime.remove(session.getSessionId());
|
||||
sessionsNotActive.remove(session.getSessionId());
|
||||
sessionidParticipantpublicidParticipant.remove(session.getSessionId());
|
||||
sessionidTokenTokenobj.remove(session.getSessionId());
|
||||
|
||||
|
|
|
@ -17,14 +17,9 @@
|
|||
|
||||
package io.openvidu.server.kurento.core;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.kurento.client.Continuation;
|
||||
import org.kurento.client.ErrorEvent;
|
||||
|
@ -35,83 +30,44 @@ import org.kurento.client.MediaPipeline;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import io.openvidu.client.OpenViduException;
|
||||
import io.openvidu.client.OpenViduException.Code;
|
||||
import io.openvidu.client.internal.ProtocolElements;
|
||||
import io.openvidu.java.client.Recording;
|
||||
import io.openvidu.java.client.RecordingLayout;
|
||||
import io.openvidu.java.client.SessionProperties;
|
||||
import io.openvidu.server.cdr.CallDetailRecord;
|
||||
import io.openvidu.server.config.OpenviduConfig;
|
||||
import io.openvidu.server.core.Participant;
|
||||
import io.openvidu.server.core.Session;
|
||||
import io.openvidu.server.recording.service.RecordingManager;
|
||||
|
||||
/**
|
||||
* @author Pablo Fuente (pablofuenteperez@gmail.com)
|
||||
*/
|
||||
public class KurentoSession implements Session {
|
||||
public class KurentoSession extends Session {
|
||||
|
||||
private final static Logger log = LoggerFactory.getLogger(Session.class);
|
||||
public static final int ASYNC_LATCH_TIMEOUT = 30;
|
||||
|
||||
private OpenviduConfig openviduConfig;
|
||||
private RecordingManager recordingManager;
|
||||
|
||||
private final ConcurrentMap<String, KurentoParticipant> participants = new ConcurrentHashMap<>();
|
||||
private String sessionId;
|
||||
private SessionProperties sessionProperties;
|
||||
private Long startTime;
|
||||
|
||||
private MediaPipeline pipeline;
|
||||
private CountDownLatch pipelineLatch = new CountDownLatch(1);
|
||||
|
||||
private KurentoClient kurentoClient;
|
||||
private KurentoSessionEventsHandler kurentoSessionHandler;
|
||||
|
||||
private volatile boolean closed = false;
|
||||
|
||||
private final ConcurrentHashMap<String, String> filterStates = new ConcurrentHashMap<>();
|
||||
private AtomicInteger activePublishers = new AtomicInteger(0);
|
||||
|
||||
private Object pipelineCreateLock = new Object();
|
||||
private Object pipelineReleaseLock = new Object();
|
||||
private volatile boolean pipelineReleased = false;
|
||||
private boolean destroyKurentoClient;
|
||||
|
||||
private CallDetailRecord CDR;
|
||||
|
||||
public final ConcurrentHashMap<String, String> publishedStreamIds = new ConcurrentHashMap<>();
|
||||
|
||||
public KurentoSession(String sessionId, Long startTime, SessionProperties sessionProperties,
|
||||
KurentoClient kurentoClient, KurentoSessionEventsHandler kurentoSessionHandler,
|
||||
boolean destroyKurentoClient, CallDetailRecord CDR, OpenviduConfig openviduConfig,
|
||||
RecordingManager recordingManager) {
|
||||
this.sessionId = sessionId;
|
||||
this.sessionProperties = sessionProperties;
|
||||
public KurentoSession(Session sessionNotActive, KurentoClient kurentoClient,
|
||||
KurentoSessionEventsHandler kurentoSessionHandler, boolean destroyKurentoClient) {
|
||||
super(sessionNotActive);
|
||||
this.kurentoClient = kurentoClient;
|
||||
this.destroyKurentoClient = destroyKurentoClient;
|
||||
this.kurentoSessionHandler = kurentoSessionHandler;
|
||||
this.CDR = CDR;
|
||||
this.openviduConfig = openviduConfig;
|
||||
this.recordingManager = recordingManager;
|
||||
this.startTime = startTime;
|
||||
log.debug("New SESSION instance with id '{}'", sessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSessionId() {
|
||||
return this.sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionProperties getSessionProperties() {
|
||||
return this.sessionProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void join(Participant participant) {
|
||||
checkClosed();
|
||||
|
@ -137,11 +93,11 @@ public class KurentoSession implements Session {
|
|||
registerPublisher();
|
||||
|
||||
// pre-load endpoints to recv video from the new publisher
|
||||
for (KurentoParticipant p : participants.values()) {
|
||||
for (Participant p : participants.values()) {
|
||||
if (participant.equals(p)) {
|
||||
continue;
|
||||
}
|
||||
p.getNewOrExistingSubscriber(participant.getParticipantPublicId());
|
||||
((KurentoParticipant) p).getNewOrExistingSubscriber(participant.getParticipantPublicId());
|
||||
}
|
||||
|
||||
log.debug("SESSION {}: Virtually subscribed other participants {} to new publisher {}", sessionId,
|
||||
|
@ -152,11 +108,11 @@ public class KurentoSession implements Session {
|
|||
deregisterPublisher();
|
||||
|
||||
// cancel recv video from this publisher
|
||||
for (KurentoParticipant subscriber : participants.values()) {
|
||||
for (Participant subscriber : participants.values()) {
|
||||
if (participant.equals(subscriber)) {
|
||||
continue;
|
||||
}
|
||||
subscriber.cancelReceivingMedia(participant.getParticipantPublicId(), reason);
|
||||
((KurentoParticipant) subscriber).cancelReceivingMedia(participant.getParticipantPublicId(), reason);
|
||||
|
||||
}
|
||||
|
||||
|
@ -170,7 +126,7 @@ public class KurentoSession implements Session {
|
|||
|
||||
checkClosed();
|
||||
|
||||
KurentoParticipant participant = participants.get(participantPrivateId);
|
||||
KurentoParticipant participant = (KurentoParticipant) participants.get(participantPrivateId);
|
||||
if (participant == null) {
|
||||
throw new OpenViduException(Code.USER_NOT_FOUND_ERROR_CODE, "Participant with private id "
|
||||
+ participantPrivateId + " not found in session '" + sessionId + "'");
|
||||
|
@ -189,36 +145,13 @@ public class KurentoSession implements Session {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Participant> getParticipants() {
|
||||
checkClosed();
|
||||
return new HashSet<Participant>(this.participants.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Participant getParticipantByPrivateId(String participantPrivateId) {
|
||||
checkClosed();
|
||||
return participants.get(participantPrivateId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Participant getParticipantByPublicId(String participantPublicId) {
|
||||
checkClosed();
|
||||
for (Participant p : participants.values()) {
|
||||
if (p.getParticipantPublicId().equals(participantPublicId)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean close(String reason) {
|
||||
if (!closed) {
|
||||
|
||||
for (KurentoParticipant participant : participants.values()) {
|
||||
participant.releaseAllFilters();
|
||||
participant.close(reason);
|
||||
for (Participant participant : participants.values()) {
|
||||
((KurentoParticipant) participant).releaseAllFilters();
|
||||
((KurentoParticipant) participant).close(reason);
|
||||
}
|
||||
|
||||
participants.clear();
|
||||
|
@ -247,17 +180,6 @@ public class KurentoSession implements Session {
|
|||
this.kurentoSessionHandler.onMediaElementError(sessionId, participantId, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
private void checkClosed() {
|
||||
if (isClosed()) {
|
||||
throw new OpenViduException(Code.ROOM_CLOSED_ERROR_CODE, "The session '" + sessionId + "' is closed");
|
||||
}
|
||||
}
|
||||
|
||||
private void removeParticipant(Participant participant, String reason) {
|
||||
|
||||
checkClosed();
|
||||
|
@ -266,24 +188,11 @@ public class KurentoSession implements Session {
|
|||
|
||||
log.debug("SESSION {}: Cancel receiving media from participant '{}' for other participant", this.sessionId,
|
||||
participant.getParticipantPublicId());
|
||||
for (KurentoParticipant other : participants.values()) {
|
||||
other.cancelReceivingMedia(participant.getParticipantPublicId(), reason);
|
||||
for (Participant other : participants.values()) {
|
||||
((KurentoParticipant) other).cancelReceivingMedia(participant.getParticipantPublicId(), reason);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActivePublishers() {
|
||||
return activePublishers.get();
|
||||
}
|
||||
|
||||
public void registerPublisher() {
|
||||
this.activePublishers.incrementAndGet();
|
||||
}
|
||||
|
||||
public void deregisterPublisher() {
|
||||
this.activePublishers.decrementAndGet();
|
||||
}
|
||||
|
||||
public MediaPipeline getPipeline() {
|
||||
try {
|
||||
pipelineLatch.await(KurentoSession.ASYNC_LATCH_TIMEOUT, TimeUnit.SECONDS);
|
||||
|
@ -361,63 +270,8 @@ public class KurentoSession implements Session {
|
|||
}
|
||||
}
|
||||
|
||||
public synchronized void updateFilter(String filterId) {
|
||||
String state = filterStates.get(filterId);
|
||||
String newState = kurentoSessionHandler.getNextFilterState(filterId, state);
|
||||
|
||||
filterStates.put(filterId, newState);
|
||||
|
||||
for (Participant participant : participants.values()) {
|
||||
kurentoSessionHandler.updateFilter(this.sessionId, participant, filterId, newState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject toJson() {
|
||||
return this.sharedJson(KurentoParticipant::toJson);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject withStatsToJson() {
|
||||
return this.sharedJson(KurentoParticipant::withStatsToJson);
|
||||
}
|
||||
|
||||
private JsonObject sharedJson(Function<KurentoParticipant, JsonObject> toJsonFunction) {
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("sessionId", this.sessionId);
|
||||
json.addProperty("createdAt", this.startTime);
|
||||
json.addProperty("mediaMode", this.sessionProperties.mediaMode().name());
|
||||
json.addProperty("recordingMode", this.sessionProperties.recordingMode().name());
|
||||
json.addProperty("defaultOutputMode", this.sessionProperties.defaultOutputMode().name());
|
||||
if (Recording.OutputMode.COMPOSED.equals(this.sessionProperties.defaultOutputMode())) {
|
||||
json.addProperty("defaultRecordingLayout", this.sessionProperties.defaultRecordingLayout().name());
|
||||
if (RecordingLayout.CUSTOM.equals(this.sessionProperties.defaultRecordingLayout())) {
|
||||
json.addProperty("defaultCustomLayout", this.sessionProperties.defaultCustomLayout());
|
||||
}
|
||||
}
|
||||
if (this.sessionProperties.customSessionId() != null) {
|
||||
json.addProperty("customSessionId", this.sessionProperties.customSessionId());
|
||||
}
|
||||
JsonObject connections = new JsonObject();
|
||||
JsonArray participants = new JsonArray();
|
||||
this.participants.values().forEach(p -> {
|
||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(p.getParticipantPublicId())) {
|
||||
participants.add(toJsonFunction.apply(p));
|
||||
}
|
||||
});
|
||||
connections.addProperty("numberOfElements", participants.size());
|
||||
connections.add("content", participants);
|
||||
json.add("connections", connections);
|
||||
return json;
|
||||
}
|
||||
|
||||
public String getParticipantPrivateIdFromStreamId(String streamId) {
|
||||
return this.publishedStreamIds.get(streamId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getStartTime() {
|
||||
return this.startTime;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -80,13 +80,19 @@ public class KurentoSessionManager extends SessionManager {
|
|||
KurentoSession session = (KurentoSession) sessions.get(sessionId);
|
||||
|
||||
if (session == null && kcSessionInfo != null) {
|
||||
SessionProperties properties = sessionProperties.get(sessionId);
|
||||
if (properties == null && this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
||||
properties = new SessionProperties.Builder().mediaMode(MediaMode.ROUTED)
|
||||
.recordingMode(RecordingMode.ALWAYS).defaultRecordingLayout(RecordingLayout.BEST_FIT)
|
||||
.build();
|
||||
// First user connecting to the session
|
||||
Session sessionNotActive = sessionsNotActive.remove(sessionId);
|
||||
|
||||
if (sessionNotActive == null && this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
||||
// Insecure user directly call joinRoom RPC method, without REST API use
|
||||
sessionNotActive = new Session(sessionId,
|
||||
new SessionProperties.Builder().mediaMode(MediaMode.ROUTED)
|
||||
.recordingMode(RecordingMode.ALWAYS)
|
||||
.defaultRecordingLayout(RecordingLayout.BEST_FIT).build(),
|
||||
CDR, openviduConfig, recordingManager);
|
||||
}
|
||||
createSession(kcSessionInfo, properties);
|
||||
|
||||
createSession(sessionNotActive, kcSessionInfo);
|
||||
}
|
||||
session = (KurentoSession) sessions.get(sessionId);
|
||||
if (session == null) {
|
||||
|
@ -489,7 +495,7 @@ public class KurentoSessionManager extends SessionManager {
|
|||
* {@link KurentoClient} that will be used by the room
|
||||
* @throws OpenViduException in case of error while creating the session
|
||||
*/
|
||||
public void createSession(KurentoClientSessionInfo kcSessionInfo, SessionProperties sessionProperties)
|
||||
public void createSession(Session sessionNotActive, KurentoClientSessionInfo kcSessionInfo)
|
||||
throws OpenViduException {
|
||||
String sessionId = kcSessionInfo.getRoomName();
|
||||
KurentoSession session = (KurentoSession) sessions.get(sessionId);
|
||||
|
@ -498,9 +504,8 @@ public class KurentoSessionManager extends SessionManager {
|
|||
"Session '" + sessionId + "' already exists");
|
||||
}
|
||||
this.kurentoClient = kcProvider.getKurentoClient(kcSessionInfo);
|
||||
session = new KurentoSession(sessionId, this.sessionCreationTime.get(sessionId), sessionProperties,
|
||||
kurentoClient, kurentoSessionEventsHandler, kcProvider.destroyWhenUnused(), this.CDR,
|
||||
this.openviduConfig, this.recordingManager);
|
||||
session = new KurentoSession(sessionNotActive, kurentoClient, kurentoSessionEventsHandler,
|
||||
kcProvider.destroyWhenUnused());
|
||||
|
||||
KurentoSession oldSession = (KurentoSession) sessions.putIfAbsent(sessionId, session);
|
||||
if (oldSession != null) {
|
||||
|
|
|
@ -158,11 +158,10 @@ public class SessionRestController {
|
|||
sessionManager.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
Long creationTime = System.currentTimeMillis();
|
||||
sessionManager.storeSessionId(sessionId, creationTime, sessionProperties);
|
||||
Session sessionNotActive = sessionManager.storeSessionNotActive(sessionId, sessionProperties);
|
||||
JsonObject responseJson = new JsonObject();
|
||||
responseJson.addProperty("id", sessionId);
|
||||
responseJson.addProperty("createdAt", creationTime);
|
||||
responseJson.addProperty("id", sessionNotActive.getSessionId());
|
||||
responseJson.addProperty("createdAt", sessionNotActive.getStartTime());
|
||||
|
||||
return new ResponseEntity<>(responseJson.toString(), getResponseHeaders(), HttpStatus.OK);
|
||||
}
|
||||
|
@ -178,10 +177,17 @@ public class SessionRestController {
|
|||
JsonObject response = (webRtcStats == true) ? session.withStatsToJson() : session.toJson();
|
||||
response.addProperty("recording", this.recordingManager.sessionIsBeingRecorded(sessionId));
|
||||
return new ResponseEntity<>(response.toString(), getResponseHeaders(), HttpStatus.OK);
|
||||
} else {
|
||||
Session sessionNotActive = this.sessionManager.getSessionNotActive(sessionId);
|
||||
if (sessionNotActive != null) {
|
||||
JsonObject response = (webRtcStats == true) ? sessionNotActive.withStatsToJson()
|
||||
: sessionNotActive.toJson();
|
||||
return new ResponseEntity<>(response.toString(), getResponseHeaders(), HttpStatus.OK);
|
||||
} else {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/sessions", method = RequestMethod.GET)
|
||||
public ResponseEntity<?> listSessions(
|
||||
|
@ -189,7 +195,7 @@ public class SessionRestController {
|
|||
|
||||
log.info("REST API: GET /api/sessions");
|
||||
|
||||
Collection<Session> sessions = this.sessionManager.getSessionObjects();
|
||||
Collection<Session> sessions = this.sessionManager.getSessionsWithNotActive();
|
||||
JsonObject json = new JsonObject();
|
||||
JsonArray jsonArray = new JsonArray();
|
||||
sessions.forEach(s -> {
|
||||
|
@ -211,10 +217,16 @@ public class SessionRestController {
|
|||
if (session != null) {
|
||||
this.sessionManager.closeSession(sessionId, "sessionClosedByServer");
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
} else {
|
||||
Session sessionNotActive = this.sessionManager.getSessionNotActive(sessionId);
|
||||
if (sessionNotActive != null) {
|
||||
this.sessionManager.closeSessionAndEmptyCollections(sessionNotActive, "sessionClosedByServer");
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
} else {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/sessions/{sessionId}/connection/{connectionId}", method = RequestMethod.DELETE)
|
||||
public ResponseEntity<?> disconnectParticipant(@PathVariable("sessionId") String sessionId,
|
||||
|
@ -232,6 +244,9 @@ public class SessionRestController {
|
|||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
} else {
|
||||
if (this.sessionManager.getSessionNotActive(sessionId) != null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
@ -250,6 +265,9 @@ public class SessionRestController {
|
|||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
} else {
|
||||
if (this.sessionManager.getSessionNotActive(sessionId) != null) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
@ -390,6 +408,10 @@ public class SessionRestController {
|
|||
Session session = sessionManager.getSession(sessionId);
|
||||
|
||||
if (session == null) {
|
||||
if (sessionManager.getSessionNotActive(sessionId) != null) {
|
||||
// Session is not active
|
||||
return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE);
|
||||
}
|
||||
// Session does not exist
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue