mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: session summary
parent
84f228a0e4
commit
86cf422c2d
|
@ -49,6 +49,7 @@ import io.openvidu.client.OpenViduException;
|
||||||
import io.openvidu.client.OpenViduException.Code;
|
import io.openvidu.client.OpenViduException.Code;
|
||||||
import io.openvidu.server.cdr.CDRLoggerFile;
|
import io.openvidu.server.cdr.CDRLoggerFile;
|
||||||
import io.openvidu.server.cdr.CallDetailRecord;
|
import io.openvidu.server.cdr.CallDetailRecord;
|
||||||
|
import io.openvidu.server.config.HttpHandshakeInterceptor;
|
||||||
import io.openvidu.server.config.OpenviduConfig;
|
import io.openvidu.server.config.OpenviduConfig;
|
||||||
import io.openvidu.server.core.SessionEventsHandler;
|
import io.openvidu.server.core.SessionEventsHandler;
|
||||||
import io.openvidu.server.core.SessionManager;
|
import io.openvidu.server.core.SessionManager;
|
||||||
|
@ -166,7 +167,8 @@ public class OpenViduServer implements JsonRpcConfigurer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerJsonRpcHandlers(JsonRpcHandlerRegistry registry) {
|
public void registerJsonRpcHandlers(JsonRpcHandlerRegistry registry) {
|
||||||
registry.addHandler(rpcHandler().withPingWatchdog(true), "/openvidu");
|
registry.addHandler(rpcHandler().withPingWatchdog(true).withInterceptors(new HttpHandshakeInterceptor()),
|
||||||
|
"/openvidu");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getContainerIp() throws IOException, InterruptedException {
|
private static String getContainerIp() throws IOException, InterruptedException {
|
||||||
|
|
|
@ -51,4 +51,16 @@ public class CDREventEnd extends CDREvent {
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getStartTime() {
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDuration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReason() {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,9 @@ public class CDREventParticipant extends CDREventEnd {
|
||||||
}
|
}
|
||||||
|
|
||||||
// participantLeft
|
// participantLeft
|
||||||
public CDREventParticipant(CDREvent event, String reason) {
|
public CDREventParticipant(CDREventParticipant event, String reason) {
|
||||||
super(CDREventName.participantLeft, event.getSessionId(), event.getTimestamp(), reason);
|
super(CDREventName.participantLeft, event.getSessionId(), event.getTimestamp(), reason);
|
||||||
this.participant = ((CDREventParticipant) event).participant;
|
this.participant = event.participant;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -46,4 +46,8 @@ public class CDREventParticipant extends CDREventEnd {
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Participant getParticipant() {
|
||||||
|
return this.participant;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,9 @@ public class CDREventRecording extends CDREventEnd {
|
||||||
}
|
}
|
||||||
|
|
||||||
// recordingStopped
|
// recordingStopped
|
||||||
public CDREventRecording(CDREvent event, String reason) {
|
public CDREventRecording(CDREventRecording event, Recording recording, String reason) {
|
||||||
super(CDREventName.recordingStopped, event.getSessionId(), event.getTimestamp(), reason);
|
super(CDREventName.recordingStopped, event.getSessionId(), event.getTimestamp(), reason);
|
||||||
this.recording = ((CDREventRecording) event).recording;
|
this.recording = recording;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -44,7 +44,8 @@ public class CDREventRecording extends CDREventEnd {
|
||||||
json.addProperty("id", this.recording.getId());
|
json.addProperty("id", this.recording.getId());
|
||||||
json.addProperty("name", this.recording.getName());
|
json.addProperty("name", this.recording.getName());
|
||||||
json.addProperty("outputMode", this.recording.getOutputMode().name());
|
json.addProperty("outputMode", this.recording.getOutputMode().name());
|
||||||
if (io.openvidu.java.client.Recording.OutputMode.COMPOSED.equals(this.recording.getOutputMode()) && this.recording.hasVideo()) {
|
if (io.openvidu.java.client.Recording.OutputMode.COMPOSED.equals(this.recording.getOutputMode())
|
||||||
|
&& this.recording.hasVideo()) {
|
||||||
json.addProperty("resolution", this.recording.getResolution());
|
json.addProperty("resolution", this.recording.getResolution());
|
||||||
json.addProperty("recordingLayout", this.recording.getRecordingLayout().name());
|
json.addProperty("recordingLayout", this.recording.getRecordingLayout().name());
|
||||||
if (RecordingLayout.CUSTOM.equals(this.recording.getRecordingLayout())
|
if (RecordingLayout.CUSTOM.equals(this.recording.getRecordingLayout())
|
||||||
|
@ -59,4 +60,8 @@ public class CDREventRecording extends CDREventEnd {
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Recording getRecording() {
|
||||||
|
return this.recording;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,13 @@ public class CDREventSession extends CDREventEnd {
|
||||||
}
|
}
|
||||||
|
|
||||||
// sessionDestroyed
|
// sessionDestroyed
|
||||||
public CDREventSession(CDREvent event, String reason) {
|
public CDREventSession(CDREventSession event, String reason) {
|
||||||
super(CDREventName.sessionDestroyed, event.getSessionId(), event.getTimestamp(), reason);
|
super(CDREventName.sessionDestroyed, event.getSessionId(), event.getTimestamp(), reason);
|
||||||
|
this.session = event.session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session getSession() {
|
||||||
|
return this.session;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,35 +20,43 @@ package io.openvidu.server.cdr;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import io.openvidu.server.core.MediaOptions;
|
import io.openvidu.server.core.MediaOptions;
|
||||||
|
import io.openvidu.server.core.Participant;
|
||||||
|
|
||||||
public class CDREventWebrtcConnection extends CDREventEnd implements Comparable<CDREventWebrtcConnection> {
|
public class CDREventWebrtcConnection extends CDREventEnd implements Comparable<CDREventWebrtcConnection> {
|
||||||
|
|
||||||
String participantId;
|
String streamId;
|
||||||
|
Participant participant;
|
||||||
MediaOptions mediaOptions;
|
MediaOptions mediaOptions;
|
||||||
String receivingFrom;
|
String receivingFrom;
|
||||||
|
|
||||||
// webrtcConnectionCreated
|
// webrtcConnectionCreated
|
||||||
public CDREventWebrtcConnection(String sessionId, String participantId, MediaOptions mediaOptions,
|
public CDREventWebrtcConnection(String sessionId, String streamId, Participant participant,
|
||||||
String receivingFrom, Long timestamp) {
|
MediaOptions mediaOptions, String receivingFrom, Long timestamp) {
|
||||||
super(CDREventName.webrtcConnectionCreated, sessionId, timestamp);
|
super(CDREventName.webrtcConnectionCreated, sessionId, timestamp);
|
||||||
this.participantId = participantId;
|
this.streamId = streamId;
|
||||||
|
this.participant = participant;
|
||||||
this.mediaOptions = mediaOptions;
|
this.mediaOptions = mediaOptions;
|
||||||
this.receivingFrom = receivingFrom;
|
this.receivingFrom = receivingFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
// webrtcConnectionDestroyed
|
// webrtcConnectionDestroyed
|
||||||
public CDREventWebrtcConnection(CDREvent event, String reason) {
|
public CDREventWebrtcConnection(CDREventWebrtcConnection event, String reason) {
|
||||||
super(CDREventName.webrtcConnectionDestroyed, event.getSessionId(), event.getTimestamp(), reason);
|
super(CDREventName.webrtcConnectionDestroyed, event.getSessionId(), event.getTimestamp(), reason);
|
||||||
CDREventWebrtcConnection e = (CDREventWebrtcConnection) event;
|
this.streamId = event.streamId;
|
||||||
this.participantId = e.participantId;
|
this.participant = event.participant;
|
||||||
this.mediaOptions = e.mediaOptions;
|
this.mediaOptions = event.mediaOptions;
|
||||||
this.receivingFrom = e.receivingFrom;
|
this.receivingFrom = event.receivingFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Participant getParticipant() {
|
||||||
|
return this.participant;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonObject toJson() {
|
public JsonObject toJson() {
|
||||||
JsonObject json = super.toJson();
|
JsonObject json = super.toJson();
|
||||||
json.addProperty("participantId", this.participantId);
|
json.addProperty("streamId", this.streamId);
|
||||||
|
json.addProperty("participantId", this.participant.getParticipantPublicId());
|
||||||
if (this.receivingFrom != null) {
|
if (this.receivingFrom != null) {
|
||||||
json.addProperty("connection", "INBOUND");
|
json.addProperty("connection", "INBOUND");
|
||||||
json.addProperty("receivingFrom", this.receivingFrom);
|
json.addProperty("receivingFrom", this.receivingFrom);
|
||||||
|
@ -66,7 +74,7 @@ public class CDREventWebrtcConnection extends CDREventEnd implements Comparable<
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(CDREventWebrtcConnection other) {
|
public int compareTo(CDREventWebrtcConnection other) {
|
||||||
if (this.participantId.equals(other.participantId)) {
|
if (this.participant.getParticipantPublicId().equals(other.participant.getParticipantPublicId())) {
|
||||||
if (this.receivingFrom != null && other.receivingFrom != null) {
|
if (this.receivingFrom != null && other.receivingFrom != null) {
|
||||||
if (this.receivingFrom.equals(other.receivingFrom)) {
|
if (this.receivingFrom.equals(other.receivingFrom)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package io.openvidu.server.cdr;
|
package io.openvidu.server.cdr;
|
||||||
|
|
||||||
import io.openvidu.server.kurento.endpoint.KmsEvent;
|
import io.openvidu.server.kurento.endpoint.KmsEvent;
|
||||||
|
import io.openvidu.server.summary.SessionSummary;
|
||||||
|
|
||||||
public interface CDRLogger {
|
public interface CDRLogger {
|
||||||
|
|
||||||
|
@ -25,6 +26,8 @@ public interface CDRLogger {
|
||||||
|
|
||||||
public void log(KmsEvent event);
|
public void log(KmsEvent event);
|
||||||
|
|
||||||
|
public void log(SessionSummary sessionSummary);
|
||||||
|
|
||||||
public boolean canBeDisabled();
|
public boolean canBeDisabled();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import io.openvidu.server.kurento.endpoint.KmsEvent;
|
import io.openvidu.server.kurento.endpoint.KmsEvent;
|
||||||
|
import io.openvidu.server.summary.SessionSummary;
|
||||||
|
|
||||||
public class CDRLoggerFile implements CDRLogger {
|
public class CDRLoggerFile implements CDRLogger {
|
||||||
|
|
||||||
|
@ -35,6 +36,10 @@ public class CDRLoggerFile implements CDRLogger {
|
||||||
public void log(KmsEvent event) {
|
public void log(KmsEvent event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log(SessionSummary sessionSummary) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeDisabled() {
|
public boolean canBeDisabled() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -30,9 +30,11 @@ import io.openvidu.server.config.OpenviduConfig;
|
||||||
import io.openvidu.server.core.MediaOptions;
|
import io.openvidu.server.core.MediaOptions;
|
||||||
import io.openvidu.server.core.Participant;
|
import io.openvidu.server.core.Participant;
|
||||||
import io.openvidu.server.core.Session;
|
import io.openvidu.server.core.Session;
|
||||||
|
import io.openvidu.server.core.SessionManager;
|
||||||
import io.openvidu.server.kurento.endpoint.KmsEvent;
|
import io.openvidu.server.kurento.endpoint.KmsEvent;
|
||||||
import io.openvidu.server.recording.Recording;
|
import io.openvidu.server.recording.Recording;
|
||||||
import io.openvidu.server.recording.service.RecordingManager;
|
import io.openvidu.server.recording.service.RecordingManager;
|
||||||
|
import io.openvidu.server.summary.SessionSummary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CDR logger to register all information of a Session.
|
* CDR logger to register all information of a Session.
|
||||||
|
@ -83,6 +85,9 @@ import io.openvidu.server.recording.service.RecordingManager;
|
||||||
*/
|
*/
|
||||||
public class CallDetailRecord {
|
public class CallDetailRecord {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected SessionManager sessionManager;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
protected OpenviduConfig openviduConfig;
|
protected OpenviduConfig openviduConfig;
|
||||||
|
|
||||||
|
@ -109,9 +114,14 @@ public class CallDetailRecord {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recordSessionDestroyed(String sessionId, String reason) {
|
public void recordSessionDestroyed(String sessionId, String reason) {
|
||||||
CDREvent e = this.sessions.remove(sessionId);
|
CDREventSession e = this.sessions.remove(sessionId);
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
this.log(new CDREventSession(e, RecordingManager.finalReason(reason)));
|
CDREventSession eventSessionEnd = new CDREventSession(e, RecordingManager.finalReason(reason));
|
||||||
|
this.log(eventSessionEnd);
|
||||||
|
|
||||||
|
// Summary: log closed session
|
||||||
|
this.log(new SessionSummary(eventSessionEnd, sessionManager.removeFinalUsers(sessionId),
|
||||||
|
sessionManager.removeAccumulatedRecordings(sessionId)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,52 +132,63 @@ public class CallDetailRecord {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recordParticipantLeft(Participant participant, String sessionId, String reason) {
|
public void recordParticipantLeft(Participant participant, String sessionId, String reason) {
|
||||||
CDREvent e = this.participants.remove(participant.getParticipantPublicId());
|
CDREventParticipant e = this.participants.remove(participant.getParticipantPublicId());
|
||||||
this.log(new CDREventParticipant(e, reason));
|
CDREventParticipant eventParticipantEnd = new CDREventParticipant(e, reason);
|
||||||
|
this.log(eventParticipantEnd);
|
||||||
|
|
||||||
|
// Summary: update final user ended connection
|
||||||
|
sessionManager.getFinalUsers(sessionId).get(participant.getFinalUserId()).setConnection(eventParticipantEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recordNewPublisher(Participant participant, String sessionId, MediaOptions mediaOptions,
|
public void recordNewPublisher(Participant participant, String sessionId, String streamId,
|
||||||
Long timestamp) {
|
MediaOptions mediaOptions, Long timestamp) {
|
||||||
CDREventWebrtcConnection publisher = new CDREventWebrtcConnection(sessionId,
|
CDREventWebrtcConnection publisher = new CDREventWebrtcConnection(sessionId, streamId, participant,
|
||||||
participant.getParticipantPublicId(), mediaOptions, null, timestamp);
|
mediaOptions, null, timestamp);
|
||||||
this.publications.put(participant.getParticipantPublicId(), publisher);
|
this.publications.put(participant.getParticipantPublicId(), publisher);
|
||||||
this.log(publisher);
|
this.log(publisher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean stopPublisher(String participantPublicId, String reason) {
|
public void stopPublisher(String participantPublicId, String streamId, String reason) {
|
||||||
CDREventWebrtcConnection publisher = this.publications.remove(participantPublicId);
|
CDREventWebrtcConnection eventPublisherEnd = this.publications.remove(participantPublicId);
|
||||||
if (publisher != null) {
|
if (eventPublisherEnd != null) {
|
||||||
publisher = new CDREventWebrtcConnection(publisher, reason);
|
eventPublisherEnd = new CDREventWebrtcConnection(eventPublisherEnd, reason);
|
||||||
this.log(publisher);
|
this.log(eventPublisherEnd);
|
||||||
return true;
|
|
||||||
|
// Summary: update final user ended publisher
|
||||||
|
sessionManager.getFinalUsers(eventPublisherEnd.getSessionId())
|
||||||
|
.get(eventPublisherEnd.getParticipant().getFinalUserId()).getConnections().get(participantPublicId)
|
||||||
|
.addPublisherClosed(streamId, eventPublisherEnd);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recordNewSubscriber(Participant participant, String sessionId, String senderPublicId, Long timestamp) {
|
public void recordNewSubscriber(Participant participant, String sessionId, String streamId, String senderPublicId,
|
||||||
|
Long timestamp) {
|
||||||
CDREventWebrtcConnection publisher = this.publications.get(senderPublicId);
|
CDREventWebrtcConnection publisher = this.publications.get(senderPublicId);
|
||||||
CDREventWebrtcConnection subscriber = new CDREventWebrtcConnection(sessionId,
|
CDREventWebrtcConnection subscriber = new CDREventWebrtcConnection(sessionId, streamId, participant,
|
||||||
participant.getParticipantPublicId(), publisher.mediaOptions, senderPublicId, timestamp);
|
publisher.mediaOptions, senderPublicId, timestamp);
|
||||||
this.subscriptions.putIfAbsent(participant.getParticipantPublicId(), new ConcurrentSkipListSet<>());
|
this.subscriptions.putIfAbsent(participant.getParticipantPublicId(), new ConcurrentSkipListSet<>());
|
||||||
this.subscriptions.get(participant.getParticipantPublicId()).add(subscriber);
|
this.subscriptions.get(participant.getParticipantPublicId()).add(subscriber);
|
||||||
this.log(subscriber);
|
this.log(subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean stopSubscriber(String participantPublicId, String senderPublicId, String reason) {
|
public void stopSubscriber(String participantPublicId, String senderPublicId, String streamId, String reason) {
|
||||||
Set<CDREventWebrtcConnection> participantSubscriptions = this.subscriptions.get(participantPublicId);
|
Set<CDREventWebrtcConnection> participantSubscriptions = this.subscriptions.get(participantPublicId);
|
||||||
if (participantSubscriptions != null) {
|
if (participantSubscriptions != null) {
|
||||||
CDREventWebrtcConnection subscription;
|
CDREventWebrtcConnection eventSubscriberEnd;
|
||||||
for (Iterator<CDREventWebrtcConnection> it = participantSubscriptions.iterator(); it.hasNext();) {
|
for (Iterator<CDREventWebrtcConnection> it = participantSubscriptions.iterator(); it.hasNext();) {
|
||||||
subscription = it.next();
|
eventSubscriberEnd = it.next();
|
||||||
if (senderPublicId.equals(subscription.receivingFrom)) {
|
if (senderPublicId.equals(eventSubscriberEnd.receivingFrom)) {
|
||||||
it.remove();
|
it.remove();
|
||||||
subscription = new CDREventWebrtcConnection(subscription, reason);
|
eventSubscriberEnd = new CDREventWebrtcConnection(eventSubscriberEnd, reason);
|
||||||
this.log(subscription);
|
this.log(eventSubscriberEnd);
|
||||||
return true;
|
|
||||||
|
// Summary: update final user ended subscriber
|
||||||
|
sessionManager.getFinalUsers(eventSubscriberEnd.getSessionId())
|
||||||
|
.get(eventSubscriberEnd.getParticipant().getFinalUserId()).getConnections()
|
||||||
|
.get(participantPublicId).addSubscriberClosed(streamId, eventSubscriberEnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recordRecordingStarted(String sessionId, Recording recording) {
|
public void recordRecordingStarted(String sessionId, Recording recording) {
|
||||||
|
@ -178,11 +199,12 @@ public class CallDetailRecord {
|
||||||
|
|
||||||
public void recordRecordingStopped(String sessionId, Recording recording, String reason) {
|
public void recordRecordingStopped(String sessionId, Recording recording, String reason) {
|
||||||
CDREventRecording recordingStartedEvent = this.recordings.remove(recording.getId());
|
CDREventRecording recordingStartedEvent = this.recordings.remove(recording.getId());
|
||||||
this.log(new CDREventRecording(recordingStartedEvent, RecordingManager.finalReason(reason)));
|
CDREventRecording recordingStoppedEvent = new CDREventRecording(recordingStartedEvent, recording,
|
||||||
}
|
RecordingManager.finalReason(reason));
|
||||||
|
this.log(recordingStoppedEvent);
|
||||||
|
|
||||||
public void recordKmsEvent(KmsEvent event) {
|
// Summary: update ended recording
|
||||||
this.log(event);
|
sessionManager.getAccumulatedRecordings(sessionId).add(recordingStoppedEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void log(CDREvent event) {
|
private void log(CDREvent event) {
|
||||||
|
@ -193,10 +215,16 @@ public class CallDetailRecord {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void log(KmsEvent event) {
|
public void log(KmsEvent event) {
|
||||||
this.loggers.forEach(logger -> {
|
this.loggers.forEach(logger -> {
|
||||||
logger.log(event);
|
logger.log(event);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void log(SessionSummary sessionSummary) {
|
||||||
|
this.loggers.forEach(logger -> {
|
||||||
|
logger.log(sessionSummary);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* (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.config;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
|
import org.springframework.http.server.ServletServerHttpRequest;
|
||||||
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.server.HandshakeInterceptor;
|
||||||
|
|
||||||
|
public class HttpHandshakeInterceptor implements HandshakeInterceptor {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HttpHandshakeInterceptor.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
|
||||||
|
Map<String, Object> attributes) throws Exception {
|
||||||
|
if (request instanceof ServletServerHttpRequest) {
|
||||||
|
HttpSession session = ((ServletServerHttpRequest) request).getServletRequest().getSession();
|
||||||
|
session.setMaxInactiveInterval(1800); // HttpSession will expire in 30 minutes
|
||||||
|
attributes.put("httpSession", session);
|
||||||
|
log.info("{} HttpSession {}", session.isNew() ? "New" : "Old", session.getId());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
|
||||||
|
Exception ex) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* (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.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import io.openvidu.server.cdr.CDREventParticipant;
|
||||||
|
import io.openvidu.server.summary.ParticipantSummary;
|
||||||
|
|
||||||
|
public class FinalUser {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String sessionId;
|
||||||
|
private String location;
|
||||||
|
private String platform;
|
||||||
|
private Map<String, ParticipantSummary> connections = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public FinalUser(String id, String sessionId, Participant firstConnection) {
|
||||||
|
this.id = id;
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
this.location = firstConnection.getLocation();
|
||||||
|
this.platform = firstConnection.getPlatform();
|
||||||
|
this.connections.put(firstConnection.getParticipantPublicId(),
|
||||||
|
new ParticipantSummary(this.sessionId, firstConnection));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSessionId() {
|
||||||
|
return sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlatform() {
|
||||||
|
return platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, ParticipantSummary> getConnections() {
|
||||||
|
return connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConnection(Participant participant) {
|
||||||
|
this.connections.put(participant.getParticipantPublicId(), new ParticipantSummary(this.sessionId, participant));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnection(CDREventParticipant event) {
|
||||||
|
ParticipantSummary oldSummary = this.connections.remove(event.getParticipant().getParticipantPublicId());
|
||||||
|
this.connections.put(event.getParticipant().getParticipantPublicId(),
|
||||||
|
new ParticipantSummary(event, oldSummary));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonObject toJson() {
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
json.addProperty("id", id);
|
||||||
|
json.addProperty("location", location);
|
||||||
|
json.addProperty("platform", platform);
|
||||||
|
|
||||||
|
JsonObject connectionsJson = new JsonObject();
|
||||||
|
connectionsJson.addProperty("numberOfElements", connections.size());
|
||||||
|
JsonArray jsonArray = new JsonArray();
|
||||||
|
connections.values().forEach(connection -> {
|
||||||
|
jsonArray.add(connection.toJson());
|
||||||
|
});
|
||||||
|
connectionsJson.add("content", jsonArray);
|
||||||
|
json.add("connections", connectionsJson);
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ import com.google.gson.JsonObject;
|
||||||
|
|
||||||
public class Participant {
|
public class Participant {
|
||||||
|
|
||||||
|
private String finalUserId; // ID to match this connection with a final user (HttpSession id)
|
||||||
private String participantPrivatetId; // ID to identify the user on server (org.kurento.jsonrpc.Session.id)
|
private String participantPrivatetId; // ID to identify the user on server (org.kurento.jsonrpc.Session.id)
|
||||||
private String participantPublicId; // ID to identify the user on clients
|
private String participantPublicId; // ID to identify the user on clients
|
||||||
private Long createdAt; // Timestamp when this connection was established
|
private Long createdAt; // Timestamp when this connection was established
|
||||||
|
@ -35,8 +36,9 @@ public class Participant {
|
||||||
|
|
||||||
private final String METADATA_SEPARATOR = "%/%";
|
private final String METADATA_SEPARATOR = "%/%";
|
||||||
|
|
||||||
public Participant(String participantPrivatetId, String participantPublicId, Token token, String clientMetadata,
|
public Participant(String finalUserId, String participantPrivatetId, String participantPublicId, Token token,
|
||||||
String location, String platform, Long createdAt) {
|
String clientMetadata, String location, String platform, Long createdAt) {
|
||||||
|
this.finalUserId = finalUserId;
|
||||||
this.participantPrivatetId = participantPrivatetId;
|
this.participantPrivatetId = participantPrivatetId;
|
||||||
this.participantPublicId = participantPublicId;
|
this.participantPublicId = participantPublicId;
|
||||||
if (createdAt != null) {
|
if (createdAt != null) {
|
||||||
|
@ -52,6 +54,10 @@ public class Participant {
|
||||||
this.platform = platform;
|
this.platform = platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFinalUserId() {
|
||||||
|
return finalUserId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getParticipantPrivateId() {
|
public String getParticipantPrivateId() {
|
||||||
return participantPrivatetId;
|
return participantPrivatetId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,6 +186,10 @@ public class SessionEventsHandler {
|
||||||
// leaving the session
|
// leaving the session
|
||||||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
|
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
||||||
|
CDR.recordParticipantLeft(participant, sessionId, reason);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPublishMedia(Participant participant, String streamId, Long createdAt, String sessionId,
|
public void onPublishMedia(Participant participant, String streamId, Long createdAt, String sessionId,
|
||||||
|
|
|
@ -19,8 +19,10 @@ package io.openvidu.server.core;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -41,6 +43,7 @@ import io.openvidu.client.internal.ProtocolElements;
|
||||||
import io.openvidu.java.client.OpenViduRole;
|
import io.openvidu.java.client.OpenViduRole;
|
||||||
import io.openvidu.java.client.SessionProperties;
|
import io.openvidu.java.client.SessionProperties;
|
||||||
import io.openvidu.server.OpenViduServer;
|
import io.openvidu.server.OpenViduServer;
|
||||||
|
import io.openvidu.server.cdr.CDREventRecording;
|
||||||
import io.openvidu.server.cdr.CallDetailRecord;
|
import io.openvidu.server.cdr.CallDetailRecord;
|
||||||
import io.openvidu.server.config.OpenviduConfig;
|
import io.openvidu.server.config.OpenviduConfig;
|
||||||
import io.openvidu.server.coturn.CoturnCredentialsService;
|
import io.openvidu.server.coturn.CoturnCredentialsService;
|
||||||
|
@ -73,6 +76,8 @@ public abstract class SessionManager {
|
||||||
protected ConcurrentMap<String, Session> sessions = new ConcurrentHashMap<>();
|
protected ConcurrentMap<String, Session> sessions = new ConcurrentHashMap<>();
|
||||||
protected ConcurrentMap<String, Session> sessionsNotActive = new ConcurrentHashMap<>();
|
protected ConcurrentMap<String, Session> sessionsNotActive = new ConcurrentHashMap<>();
|
||||||
protected ConcurrentMap<String, ConcurrentHashMap<String, Participant>> sessionidParticipantpublicidParticipant = new ConcurrentHashMap<>();
|
protected ConcurrentMap<String, ConcurrentHashMap<String, Participant>> sessionidParticipantpublicidParticipant = new ConcurrentHashMap<>();
|
||||||
|
protected ConcurrentMap<String, ConcurrentHashMap<String, FinalUser>> sessionidFinalUsers = new ConcurrentHashMap<>();
|
||||||
|
protected ConcurrentMap<String, ConcurrentLinkedQueue<CDREventRecording>> sessionidAccumulatedRecordings = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
protected ConcurrentMap<String, Boolean> insecureUsers = new ConcurrentHashMap<>();
|
protected ConcurrentMap<String, Boolean> insecureUsers = new ConcurrentHashMap<>();
|
||||||
public ConcurrentMap<String, ConcurrentHashMap<String, Token>> sessionidTokenTokenobj = new ConcurrentHashMap<>();
|
public ConcurrentMap<String, ConcurrentHashMap<String, Token>> sessionidTokenTokenobj = new ConcurrentHashMap<>();
|
||||||
|
@ -214,6 +219,22 @@ public abstract class SessionManager {
|
||||||
"No participant with private id '" + participantPrivateId + "' was found");
|
"No participant with private id '" + participantPrivateId + "' was found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, FinalUser> getFinalUsers(String sessionId) {
|
||||||
|
return this.sessionidFinalUsers.get(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, FinalUser> removeFinalUsers(String sessionId) {
|
||||||
|
return this.sessionidFinalUsers.remove(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<CDREventRecording> getAccumulatedRecordings(String sessionId) {
|
||||||
|
return this.sessionidAccumulatedRecordings.get(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<CDREventRecording> removeAccumulatedRecordings(String sessionId) {
|
||||||
|
return this.sessionidAccumulatedRecordings.remove(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
public MediaOptions generateMediaOptions(Request<JsonObject> request) {
|
public MediaOptions generateMediaOptions(Request<JsonObject> request) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -222,6 +243,10 @@ public abstract class SessionManager {
|
||||||
Session sessionNotActive = new Session(sessionId, sessionProperties, CDR, openviduConfig, recordingManager);
|
Session sessionNotActive = new Session(sessionId, sessionProperties, CDR, openviduConfig, recordingManager);
|
||||||
this.sessionsNotActive.put(sessionId, sessionNotActive);
|
this.sessionsNotActive.put(sessionId, sessionNotActive);
|
||||||
this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
||||||
|
this.sessionidFinalUsers.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
||||||
|
if (this.openviduConfig.isRecordingModuleEnabled()) {
|
||||||
|
this.sessionidAccumulatedRecordings.putIfAbsent(sessionId, new ConcurrentLinkedQueue<>());
|
||||||
|
}
|
||||||
showTokens();
|
showTokens();
|
||||||
return sessionNotActive;
|
return sessionNotActive;
|
||||||
}
|
}
|
||||||
|
@ -272,6 +297,10 @@ public abstract class SessionManager {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
this.sessionidParticipantpublicidParticipant.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
||||||
|
this.sessionidFinalUsers.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
||||||
|
if (this.openviduConfig.isRecordingModuleEnabled()) {
|
||||||
|
this.sessionidAccumulatedRecordings.putIfAbsent(sessionId, new ConcurrentLinkedQueue<>());
|
||||||
|
}
|
||||||
this.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
this.sessionidTokenTokenobj.putIfAbsent(sessionId, new ConcurrentHashMap<>());
|
||||||
this.sessionidTokenTokenobj.get(sessionId).putIfAbsent(token,
|
this.sessionidTokenTokenobj.get(sessionId).putIfAbsent(token,
|
||||||
new Token(token, OpenViduRole.PUBLISHER, "",
|
new Token(token, OpenViduRole.PUBLISHER, "",
|
||||||
|
@ -321,16 +350,30 @@ public abstract class SessionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Participant newParticipant(String sessionId, String participantPrivatetId, Token token,
|
public Participant newParticipant(String sessionId, String participantPrivatetId, Token token,
|
||||||
String clientMetadata, String location, String platform) {
|
String clientMetadata, String location, String platform, String finalUserId) {
|
||||||
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
||||||
String participantPublicId = this.generateRandomChain();
|
String participantPublicId = this.generateRandomChain();
|
||||||
Participant p = new Participant(participantPrivatetId, participantPublicId, token, clientMetadata, location,
|
Participant p = new Participant(finalUserId, participantPrivatetId, participantPublicId, token,
|
||||||
platform, null);
|
clientMetadata, location, platform, null);
|
||||||
while (this.sessionidParticipantpublicidParticipant.get(sessionId).putIfAbsent(participantPublicId,
|
while (this.sessionidParticipantpublicidParticipant.get(sessionId).putIfAbsent(participantPublicId,
|
||||||
p) != null) {
|
p) != null) {
|
||||||
participantPublicId = this.generateRandomChain();
|
participantPublicId = this.generateRandomChain();
|
||||||
p.setParticipantPublicId(participantPublicId);
|
p.setParticipantPublicId(participantPublicId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FinalUser finalUser = this.sessionidFinalUsers.get(sessionId).get(finalUserId);
|
||||||
|
if (finalUser == null) {
|
||||||
|
// First connection for new final user
|
||||||
|
log.info("Participant {} of session {} belongs to a new final user", p.getParticipantPublicId(),
|
||||||
|
sessionId);
|
||||||
|
this.sessionidFinalUsers.get(sessionId).put(finalUserId, new FinalUser(finalUserId, sessionId, p));
|
||||||
|
} else {
|
||||||
|
// New connection for previously existing final user
|
||||||
|
log.info("Participant {} of session {} belongs to a previously existing user",
|
||||||
|
p.getParticipantPublicId(), sessionId);
|
||||||
|
finalUser.addConnection(p);
|
||||||
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
} else {
|
} else {
|
||||||
throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId);
|
throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId);
|
||||||
|
@ -340,7 +383,7 @@ public abstract class SessionManager {
|
||||||
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) {
|
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
||||||
Participant p = new Participant(participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID,
|
Participant p = new Participant(null, participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID,
|
||||||
token, clientMetadata, null, null, null);
|
token, clientMetadata, null, null, null);
|
||||||
this.sessionidParticipantpublicidParticipant.get(sessionId)
|
this.sessionidParticipantpublicidParticipant.get(sessionId)
|
||||||
.put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p);
|
.put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p);
|
||||||
|
@ -445,6 +488,8 @@ public abstract class SessionManager {
|
||||||
sessions.remove(session.getSessionId());
|
sessions.remove(session.getSessionId());
|
||||||
sessionsNotActive.remove(session.getSessionId());
|
sessionsNotActive.remove(session.getSessionId());
|
||||||
sessionidParticipantpublicidParticipant.remove(session.getSessionId());
|
sessionidParticipantpublicidParticipant.remove(session.getSessionId());
|
||||||
|
sessionidFinalUsers.remove(session.getSessionId());
|
||||||
|
sessionidAccumulatedRecordings.remove(session.getSessionId());
|
||||||
sessionidTokenTokenobj.remove(session.getSessionId());
|
sessionidTokenTokenobj.remove(session.getSessionId());
|
||||||
|
|
||||||
log.warn("Session '{}' removed and closed", session.getSessionId());
|
log.warn("Session '{}' removed and closed", session.getSessionId());
|
||||||
|
|
|
@ -77,9 +77,9 @@ public class KurentoParticipant extends Participant {
|
||||||
|
|
||||||
public KurentoParticipant(Participant participant, KurentoSession kurentoSession, InfoHandler infoHandler,
|
public KurentoParticipant(Participant participant, KurentoSession kurentoSession, InfoHandler infoHandler,
|
||||||
CallDetailRecord CDR, OpenviduConfig openviduConfig, RecordingManager recordingManager) {
|
CallDetailRecord CDR, OpenviduConfig openviduConfig, RecordingManager recordingManager) {
|
||||||
super(participant.getParticipantPrivateId(), participant.getParticipantPublicId(), participant.getToken(),
|
super(participant.getFinalUserId(), participant.getParticipantPrivateId(), participant.getParticipantPublicId(),
|
||||||
participant.getClientMetadata(), participant.getLocation(), participant.getPlatform(),
|
participant.getToken(), participant.getClientMetadata(), participant.getLocation(),
|
||||||
participant.getCreatedAt());
|
participant.getPlatform(), participant.getCreatedAt());
|
||||||
this.infoHandler = infoHandler;
|
this.infoHandler = infoHandler;
|
||||||
this.CDR = CDR;
|
this.CDR = CDR;
|
||||||
this.openviduConfig = openviduConfig;
|
this.openviduConfig = openviduConfig;
|
||||||
|
@ -185,8 +185,8 @@ public class KurentoParticipant extends Participant {
|
||||||
this.recordingManager.startOneIndividualStreamRecording(session, null, null, this);
|
this.recordingManager.startOneIndividualStreamRecording(session, null, null, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CDR.recordNewPublisher(this, this.session.getSessionId(), this.publisher.getMediaOptions(),
|
CDR.recordNewPublisher(this, session.getSessionId(), publisher.getStreamId(), publisher.getMediaOptions(),
|
||||||
this.publisher.createdAt());
|
publisher.createdAt());
|
||||||
|
|
||||||
return sdpResponse;
|
return sdpResponse;
|
||||||
}
|
}
|
||||||
|
@ -270,8 +270,8 @@ public class KurentoParticipant extends Participant {
|
||||||
senderName, this.session.getSessionId());
|
senderName, this.session.getSessionId());
|
||||||
|
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(this.getParticipantPublicId())) {
|
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(this.getParticipantPublicId())) {
|
||||||
CDR.recordNewSubscriber(this, this.session.getSessionId(), sender.getParticipantPublicId(),
|
CDR.recordNewSubscriber(this, this.session.getSessionId(), sender.getPublisherStreamId(),
|
||||||
subscriber.createdAt());
|
sender.getParticipantPublicId(), subscriber.createdAt());
|
||||||
}
|
}
|
||||||
|
|
||||||
return sdpAnswer;
|
return sdpAnswer;
|
||||||
|
@ -386,10 +386,10 @@ public class KurentoParticipant extends Participant {
|
||||||
}
|
}
|
||||||
releaseElement(getParticipantPublicId(), publisher.getEndpoint());
|
releaseElement(getParticipantPublicId(), publisher.getEndpoint());
|
||||||
this.streaming = false;
|
this.streaming = false;
|
||||||
publisher = null;
|
|
||||||
this.session.deregisterPublisher();
|
this.session.deregisterPublisher();
|
||||||
|
|
||||||
CDR.stopPublisher(this.getParticipantPublicId(), reason);
|
CDR.stopPublisher(this.getParticipantPublicId(), publisher.getStreamId(), reason);
|
||||||
|
publisher = null;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.warn("PARTICIPANT {}: Trying to release publisher endpoint but is null", getParticipantPublicId());
|
log.warn("PARTICIPANT {}: Trying to release publisher endpoint but is null", getParticipantPublicId());
|
||||||
|
@ -402,7 +402,7 @@ public class KurentoParticipant extends Participant {
|
||||||
releaseElement(senderName, subscriber.getEndpoint());
|
releaseElement(senderName, subscriber.getEndpoint());
|
||||||
|
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(this.getParticipantPublicId())) {
|
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(this.getParticipantPublicId())) {
|
||||||
CDR.stopSubscriber(this.getParticipantPublicId(), senderName, reason);
|
CDR.stopSubscriber(this.getParticipantPublicId(), senderName, subscriber.getStreamId(), reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -442,7 +442,7 @@ public class KurentoParticipant extends Participant {
|
||||||
KmsEvent kmsEvent = new KmsMediaEvent(event, endpoint.getEndpointName(), event.getMediaType(),
|
KmsEvent kmsEvent = new KmsMediaEvent(event, endpoint.getEndpointName(), event.getMediaType(),
|
||||||
endpoint.createdAt());
|
endpoint.createdAt());
|
||||||
endpoint.kmsEvents.add(kmsEvent);
|
endpoint.kmsEvents.add(kmsEvent);
|
||||||
this.CDR.recordKmsEvent(kmsEvent);
|
this.CDR.log(kmsEvent);
|
||||||
this.infoHandler.sendInfo(msg);
|
this.infoHandler.sendInfo(msg);
|
||||||
log.info(msg);
|
log.info(msg);
|
||||||
});
|
});
|
||||||
|
@ -454,7 +454,7 @@ public class KurentoParticipant extends Participant {
|
||||||
KmsEvent kmsEvent = new KmsMediaEvent(event, endpoint.getEndpointName(), event.getMediaType(),
|
KmsEvent kmsEvent = new KmsMediaEvent(event, endpoint.getEndpointName(), event.getMediaType(),
|
||||||
endpoint.createdAt());
|
endpoint.createdAt());
|
||||||
endpoint.kmsEvents.add(kmsEvent);
|
endpoint.kmsEvents.add(kmsEvent);
|
||||||
this.CDR.recordKmsEvent(kmsEvent);
|
this.CDR.log(kmsEvent);
|
||||||
this.infoHandler.sendInfo(msg);
|
this.infoHandler.sendInfo(msg);
|
||||||
log.info(msg);
|
log.info(msg);
|
||||||
});
|
});
|
||||||
|
@ -464,7 +464,7 @@ public class KurentoParticipant extends Participant {
|
||||||
+ typeOfEndpoint + ") | timestamp: " + event.getTimestamp();
|
+ typeOfEndpoint + ") | timestamp: " + event.getTimestamp();
|
||||||
KmsEvent kmsEvent = new KmsEvent(event, endpoint.getEndpointName(), endpoint.createdAt());
|
KmsEvent kmsEvent = new KmsEvent(event, endpoint.getEndpointName(), endpoint.createdAt());
|
||||||
endpoint.kmsEvents.add(kmsEvent);
|
endpoint.kmsEvents.add(kmsEvent);
|
||||||
this.CDR.recordKmsEvent(kmsEvent);
|
this.CDR.log(kmsEvent);
|
||||||
this.infoHandler.sendInfo(msg);
|
this.infoHandler.sendInfo(msg);
|
||||||
log.info(msg);
|
log.info(msg);
|
||||||
});
|
});
|
||||||
|
@ -475,7 +475,7 @@ public class KurentoParticipant extends Participant {
|
||||||
+ " | timestamp: " + event.getTimestamp();
|
+ " | timestamp: " + event.getTimestamp();
|
||||||
KmsEvent kmsEvent = new KmsEvent(event, endpoint.getEndpointName(), endpoint.createdAt());
|
KmsEvent kmsEvent = new KmsEvent(event, endpoint.getEndpointName(), endpoint.createdAt());
|
||||||
endpoint.kmsEvents.add(kmsEvent);
|
endpoint.kmsEvents.add(kmsEvent);
|
||||||
this.CDR.recordKmsEvent(kmsEvent);
|
this.CDR.log(kmsEvent);
|
||||||
this.infoHandler.sendInfo(msg);
|
this.infoHandler.sendInfo(msg);
|
||||||
log.info(msg);
|
log.info(msg);
|
||||||
});
|
});
|
||||||
|
@ -488,7 +488,7 @@ public class KurentoParticipant extends Participant {
|
||||||
+ endpoint.selectedRemoteIceCandidate + " | timestamp: " + event.getTimestamp();
|
+ endpoint.selectedRemoteIceCandidate + " | timestamp: " + event.getTimestamp();
|
||||||
KmsEvent kmsEvent = new KmsEvent(event, endpoint.getEndpointName(), endpoint.createdAt());
|
KmsEvent kmsEvent = new KmsEvent(event, endpoint.getEndpointName(), endpoint.createdAt());
|
||||||
endpoint.kmsEvents.add(kmsEvent);
|
endpoint.kmsEvents.add(kmsEvent);
|
||||||
this.CDR.recordKmsEvent(kmsEvent);
|
this.CDR.log(kmsEvent);
|
||||||
this.infoHandler.sendInfo(msg);
|
this.infoHandler.sendInfo(msg);
|
||||||
log.info(msg);
|
log.info(msg);
|
||||||
});
|
});
|
||||||
|
@ -500,7 +500,7 @@ public class KurentoParticipant extends Participant {
|
||||||
KmsEvent kmsEvent = new KmsMediaEvent(event, endpoint.getEndpointName(), event.getMediaType(),
|
KmsEvent kmsEvent = new KmsMediaEvent(event, endpoint.getEndpointName(), event.getMediaType(),
|
||||||
endpoint.createdAt());
|
endpoint.createdAt());
|
||||||
endpoint.kmsEvents.add(kmsEvent);
|
endpoint.kmsEvents.add(kmsEvent);
|
||||||
this.CDR.recordKmsEvent(kmsEvent);
|
this.CDR.log(kmsEvent);
|
||||||
this.infoHandler.sendInfo(msg);
|
this.infoHandler.sendInfo(msg);
|
||||||
log.info(msg);
|
log.info(msg);
|
||||||
});
|
});
|
||||||
|
@ -513,7 +513,7 @@ public class KurentoParticipant extends Participant {
|
||||||
+ event.getTimestamp();
|
+ event.getTimestamp();
|
||||||
KmsEvent kmsEvent = new KmsEvent(event, endpoint.getEndpointName(), endpoint.createdAt());
|
KmsEvent kmsEvent = new KmsEvent(event, endpoint.getEndpointName(), endpoint.createdAt());
|
||||||
endpoint.kmsEvents.add(kmsEvent);
|
endpoint.kmsEvents.add(kmsEvent);
|
||||||
this.CDR.recordKmsEvent(kmsEvent);
|
this.CDR.log(kmsEvent);
|
||||||
this.infoHandler.sendInfo(msg);
|
this.infoHandler.sendInfo(msg);
|
||||||
log.info(msg);
|
log.info(msg);
|
||||||
// }
|
// }
|
||||||
|
@ -525,7 +525,7 @@ public class KurentoParticipant extends Participant {
|
||||||
+ " | timestamp: " + event.getTimestamp();
|
+ " | timestamp: " + event.getTimestamp();
|
||||||
KmsEvent kmsEvent = new KmsEvent(event, endpoint.getEndpointName(), endpoint.createdAt());
|
KmsEvent kmsEvent = new KmsEvent(event, endpoint.getEndpointName(), endpoint.createdAt());
|
||||||
endpoint.kmsEvents.add(kmsEvent);
|
endpoint.kmsEvents.add(kmsEvent);
|
||||||
this.CDR.recordKmsEvent(kmsEvent);
|
this.CDR.log(kmsEvent);
|
||||||
this.infoHandler.sendInfo(msg);
|
this.infoHandler.sendInfo(msg);
|
||||||
log.error(msg);
|
log.error(msg);
|
||||||
});
|
});
|
||||||
|
|
|
@ -136,10 +136,6 @@ public class KurentoSession extends Session {
|
||||||
|
|
||||||
this.removeParticipant(participant, reason);
|
this.removeParticipant(participant, reason);
|
||||||
participant.close(reason, true);
|
participant.close(reason, true);
|
||||||
|
|
||||||
if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
|
|
||||||
CDR.recordParticipantLeft(participant, participant.getSession().getSessionId(), reason);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -77,9 +77,9 @@ 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 kSession = (KurentoSession) sessions.get(sessionId);
|
||||||
|
|
||||||
if (session == null && kcSessionInfo != null) {
|
if (kSession == null && kcSessionInfo != null) {
|
||||||
// First user connecting to the session
|
// First user connecting to the session
|
||||||
Session sessionNotActive = sessionsNotActive.remove(sessionId);
|
Session sessionNotActive = sessionsNotActive.remove(sessionId);
|
||||||
|
|
||||||
|
@ -94,21 +94,20 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
|
|
||||||
createSession(sessionNotActive, kcSessionInfo);
|
createSession(sessionNotActive, kcSessionInfo);
|
||||||
}
|
}
|
||||||
session = (KurentoSession) sessions.get(sessionId);
|
kSession = (KurentoSession) sessions.get(sessionId);
|
||||||
if (session == null) {
|
if (kSession == 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
|
||||||
+ "' was not found, must be created before '" + sessionId + "' can join");
|
+ "' was not found, must be created before '" + sessionId + "' can join");
|
||||||
}
|
}
|
||||||
if (session.isClosed()) {
|
if (kSession.isClosed()) {
|
||||||
log.warn("'{}' is trying to join session '{}' but it is closing", participant.getParticipantPublicId(),
|
log.warn("'{}' is trying to join session '{}' but it is closing", participant.getParticipantPublicId(),
|
||||||
sessionId);
|
sessionId);
|
||||||
throw new OpenViduException(Code.ROOM_CLOSED_ERROR_CODE, "'" + participant.getParticipantPublicId()
|
throw new OpenViduException(Code.ROOM_CLOSED_ERROR_CODE, "'" + participant.getParticipantPublicId()
|
||||||
+ "' is trying to join session '" + sessionId + "' but it is closing");
|
+ "' is trying to join session '" + sessionId + "' but it is closing");
|
||||||
}
|
}
|
||||||
existingParticipants = getParticipants(sessionId);
|
existingParticipants = getParticipants(sessionId);
|
||||||
session.join(participant);
|
kSession.join(participant);
|
||||||
|
|
||||||
} catch (OpenViduException e) {
|
} catch (OpenViduException e) {
|
||||||
log.warn("PARTICIPANT {}: Error joining/creating session {}", participant.getParticipantPublicId(),
|
log.warn("PARTICIPANT {}: Error joining/creating session {}", participant.getParticipantPublicId(),
|
||||||
sessionId, e);
|
sessionId, e);
|
||||||
|
|
|
@ -24,6 +24,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 javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -186,6 +188,34 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpSession httpSession = (HttpSession) rpcConnection.getSession().getAttributes().get("httpSession");
|
||||||
|
|
||||||
|
JsonObject sessions = (JsonObject) httpSession.getAttribute("openviduSessions");
|
||||||
|
if (sessions == null) {
|
||||||
|
// First time this final user connects to an OpenVidu session in this active
|
||||||
|
// WebSocketSession. This is a new final user connecting to OpenVidu Server
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
json.addProperty(sessionId, System.currentTimeMillis());
|
||||||
|
httpSession.setAttribute("openviduSessions", json);
|
||||||
|
} else {
|
||||||
|
// This final user has already been connected to an OpenVidu session in this
|
||||||
|
// active WebSocketSession
|
||||||
|
if (sessions.has(sessionId)) {
|
||||||
|
if (sessionManager.getSession(sessionId) != null) {
|
||||||
|
// The previously existing final user is reconnecting to an OpenVidu session
|
||||||
|
log.info("Final user reconnecting");
|
||||||
|
} else if (sessionManager.getSessionNotActive(sessionId) != null) {
|
||||||
|
// The previously existing final user is the first one connecting to a new
|
||||||
|
// OpenVidu session that shares a sessionId with a previously closed session
|
||||||
|
// (same customSessionId)
|
||||||
|
sessions.addProperty(sessionId, System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The previously existing final user is connecting to a new session
|
||||||
|
sessions.addProperty(sessionId, System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean recorder = false;
|
boolean recorder = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -218,7 +248,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
clientMetadata);
|
clientMetadata);
|
||||||
} else {
|
} else {
|
||||||
participant = sessionManager.newParticipant(sessionId, participantPrivatetId, tokenObj,
|
participant = sessionManager.newParticipant(sessionId, participantPrivatetId, tokenObj,
|
||||||
clientMetadata, location, platform);
|
clientMetadata, location, platform, httpSession.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcConnection.setSessionId(sessionId);
|
rpcConnection.setSessionId(sessionId);
|
||||||
|
@ -555,6 +585,10 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
|
||||||
address = ((WebSocketServerSession) rpcSession).getWebSocketSession().getRemoteAddress().getAddress();
|
address = ((WebSocketServerSession) rpcSession).getWebSocketSession().getRemoteAddress().getAddress();
|
||||||
}
|
}
|
||||||
rpcSession.getAttributes().put("remoteAddress", address);
|
rpcSession.getAttributes().put("remoteAddress", address);
|
||||||
|
|
||||||
|
HttpSession httpSession = (HttpSession) ((WebSocketServerSession) rpcSession).getWebSocketSession()
|
||||||
|
.getAttributes().get("httpSession");
|
||||||
|
rpcSession.getAttributes().put("httpSession", httpSession);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* (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.summary;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import io.openvidu.server.cdr.CDREventParticipant;
|
||||||
|
import io.openvidu.server.cdr.CDREventWebrtcConnection;
|
||||||
|
import io.openvidu.server.core.Participant;
|
||||||
|
|
||||||
|
public class ParticipantSummary {
|
||||||
|
|
||||||
|
private CDREventParticipant eventParticipantEnd;
|
||||||
|
private Map<String, CDREventWebrtcConnection> publishers = new ConcurrentHashMap<>();
|
||||||
|
private Map<String, CDREventWebrtcConnection> subscribers = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public ParticipantSummary(CDREventParticipant event) {
|
||||||
|
this.eventParticipantEnd = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParticipantSummary(CDREventParticipant event, ParticipantSummary oldSummary) {
|
||||||
|
this.eventParticipantEnd = event;
|
||||||
|
this.publishers = oldSummary.publishers;
|
||||||
|
this.subscribers = oldSummary.subscribers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParticipantSummary(String sessionId, Participant participant) {
|
||||||
|
this.eventParticipantEnd = new CDREventParticipant(sessionId, participant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPublisherClosed(String streamId, CDREventWebrtcConnection event) {
|
||||||
|
this.publishers.put(streamId, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSubscriberClosed(String streamId, CDREventWebrtcConnection event) {
|
||||||
|
this.subscribers.put(streamId, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonObject toJson() {
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
|
||||||
|
json.addProperty("createdAt", this.eventParticipantEnd.getStartTime());
|
||||||
|
json.addProperty("destroyedAt", this.eventParticipantEnd.getTimestamp());
|
||||||
|
|
||||||
|
Participant p = this.eventParticipantEnd.getParticipant();
|
||||||
|
json.addProperty("connectionId", p.getParticipantPublicId());
|
||||||
|
json.addProperty("clientData", p.getClientMetadata());
|
||||||
|
json.addProperty("serverData", p.getServerMetadata());
|
||||||
|
|
||||||
|
long duration = (this.eventParticipantEnd.getTimestamp() - this.eventParticipantEnd.getStartTime()) / 1000;
|
||||||
|
json.addProperty("duration", duration);
|
||||||
|
|
||||||
|
json.addProperty("reason", this.eventParticipantEnd.getReason());
|
||||||
|
|
||||||
|
// Publishers summary
|
||||||
|
JsonObject publishersJson = new JsonObject();
|
||||||
|
publishersJson.addProperty("numberOfElements", publishers.size());
|
||||||
|
JsonArray jsonArrayPublishers = new JsonArray();
|
||||||
|
publishers.values().forEach(cdrEvent -> {
|
||||||
|
JsonObject j = cdrEvent.toJson();
|
||||||
|
j.remove("participantId");
|
||||||
|
j.remove("connection");
|
||||||
|
jsonArrayPublishers.add(j);
|
||||||
|
});
|
||||||
|
publishersJson.add("content", jsonArrayPublishers);
|
||||||
|
json.add("publishers", publishersJson);
|
||||||
|
|
||||||
|
// Subscribers summary
|
||||||
|
JsonObject subscribersJson = new JsonObject();
|
||||||
|
subscribersJson.addProperty("numberOfElements", subscribers.size());
|
||||||
|
JsonArray jsonArraySubscribers = new JsonArray();
|
||||||
|
subscribers.values().forEach(cdrEvent -> {
|
||||||
|
JsonObject j = cdrEvent.toJson();
|
||||||
|
j.remove("participantId");
|
||||||
|
j.remove("connection");
|
||||||
|
jsonArraySubscribers.add(j);
|
||||||
|
});
|
||||||
|
subscribersJson.add("content", jsonArraySubscribers);
|
||||||
|
json.add("subscribers", subscribersJson);
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* (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.summary;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import io.openvidu.server.cdr.CDREventRecording;
|
||||||
|
import io.openvidu.server.cdr.CDREventSession;
|
||||||
|
import io.openvidu.server.core.FinalUser;
|
||||||
|
|
||||||
|
public class SessionSummary {
|
||||||
|
|
||||||
|
private long totalStreamedMinutes; // Minutes
|
||||||
|
private CDREventSession eventSessionEnd;
|
||||||
|
private Map<String, FinalUser> users;
|
||||||
|
private Collection<CDREventRecording> recordings;
|
||||||
|
|
||||||
|
public SessionSummary(CDREventSession event, Map<String, FinalUser> users,
|
||||||
|
Collection<CDREventRecording> recordings) {
|
||||||
|
this.eventSessionEnd = event;
|
||||||
|
this.users = users;
|
||||||
|
this.recordings = recordings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonObject toJson() {
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
json.addProperty("createdAt", this.eventSessionEnd.getStartTime());
|
||||||
|
json.addProperty("destroyedAt", this.eventSessionEnd.getTimestamp());
|
||||||
|
json.addProperty("sessionId", this.eventSessionEnd.getSessionId());
|
||||||
|
json.addProperty("customSessionId", this.eventSessionEnd.getSession().getSessionProperties().customSessionId());
|
||||||
|
json.addProperty("mediaMode", this.eventSessionEnd.getSession().getSessionProperties().mediaMode().name());
|
||||||
|
json.addProperty("recordingMode",
|
||||||
|
this.eventSessionEnd.getSession().getSessionProperties().recordingMode().name());
|
||||||
|
|
||||||
|
long duration = (this.eventSessionEnd.getTimestamp() - this.eventSessionEnd.getStartTime()) / 1000;
|
||||||
|
json.addProperty("duration", duration);
|
||||||
|
|
||||||
|
json.addProperty("reason", this.eventSessionEnd.getReason());
|
||||||
|
|
||||||
|
// Final users
|
||||||
|
JsonObject usersJson = new JsonObject();
|
||||||
|
usersJson.addProperty("numberOfElements", users.size());
|
||||||
|
JsonArray jsonArray = new JsonArray();
|
||||||
|
users.values().forEach(finalUser -> {
|
||||||
|
jsonArray.add(finalUser.toJson());
|
||||||
|
});
|
||||||
|
usersJson.add("content", jsonArray);
|
||||||
|
json.add("users", usersJson);
|
||||||
|
|
||||||
|
// Accumulated recordings
|
||||||
|
JsonObject recordingsJson = new JsonObject();
|
||||||
|
recordingsJson.addProperty("numberOfElements", recordings.size());
|
||||||
|
JsonArray jsonRecordingsArray = new JsonArray();
|
||||||
|
recordings.forEach(rec -> {
|
||||||
|
jsonRecordingsArray.add(rec.toJson());
|
||||||
|
});
|
||||||
|
recordingsJson.add("content", jsonRecordingsArray);
|
||||||
|
json.add("recordings", recordingsJson);
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2489,7 +2489,7 @@ public class OpenViduTestAppE2eTest {
|
||||||
|
|
||||||
user.getEventManager().waitUntilEventReaches("recordingStarted", 2);
|
user.getEventManager().waitUntilEventReaches("recordingStarted", 2);
|
||||||
|
|
||||||
Thread.sleep(1000);
|
Thread.sleep(2000);
|
||||||
|
|
||||||
// 409 (already recording)
|
// 409 (already recording)
|
||||||
restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_CONFLICT);
|
restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_CONFLICT);
|
||||||
|
|
Loading…
Reference in New Issue