mirror of https://github.com/OpenVidu/openvidu.git
CDR extended (session, participant and webrtc events)
parent
33e4009545
commit
7ce9ceb530
|
@ -106,10 +106,6 @@
|
||||||
<artifactId>kurento-jsonrpc-server</artifactId>
|
<artifactId>kurento-jsonrpc-server</artifactId>
|
||||||
<version>${version.kurento}</version>
|
<version>${version.kurento}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-logging</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||||
|
@ -201,9 +197,9 @@
|
||||||
<version>2.2.2</version>
|
<version>2.2.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>slf4j-log4j12</artifactId>
|
<artifactId>spring-boot-starter-logging</artifactId>
|
||||||
<version>1.7.25</version>
|
<version>${version.spring-boot}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Test dependencies -->
|
<!-- Test dependencies -->
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
package io.openvidu.server.cdr;
|
||||||
|
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
import io.openvidu.server.core.MediaOptions;
|
||||||
|
import io.openvidu.server.core.Participant;
|
||||||
|
|
||||||
|
public class CDREvent implements Comparable<CDREvent> {
|
||||||
|
|
||||||
|
static final String SESSION_CREATED = "sessionCreated";
|
||||||
|
static final String SESSION_DESTROYED = "sessionDestroyed";
|
||||||
|
static final String PARTICIPANT_JOINED = "participantJoined";
|
||||||
|
static final String PARTICIPANT_LEFT = "participantLeft";
|
||||||
|
static final String CONNECTION_CREATED = "webrtcConnectionCreated";
|
||||||
|
static final String CONNECTION_DESTROYED = "webrtcConnectionDestroyed";
|
||||||
|
|
||||||
|
protected String eventName;
|
||||||
|
protected String sessionId;
|
||||||
|
private Participant participant;
|
||||||
|
private MediaOptions mediaOptions;
|
||||||
|
private String receivingFrom;
|
||||||
|
private Long startTime;
|
||||||
|
private Integer duration;
|
||||||
|
protected Long timeStamp;
|
||||||
|
|
||||||
|
public CDREvent(String eventName, CDREvent event) {
|
||||||
|
this(eventName, event.participant, event.sessionId, event.mediaOptions, event.receivingFrom, event.startTime);
|
||||||
|
this.duration = (int) (this.timeStamp - this.startTime / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CDREvent(String eventName, String sessionId) {
|
||||||
|
this.eventName = eventName;
|
||||||
|
if ((sessionId.indexOf('/')) != -1) {
|
||||||
|
this.sessionId = sessionId.substring(sessionId.lastIndexOf('/') + 1, sessionId.length());
|
||||||
|
} else {
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
}
|
||||||
|
this.timeStamp = System.currentTimeMillis();
|
||||||
|
this.startTime = this.timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CDREvent(String eventName, Participant participant, String sessionId) {
|
||||||
|
this(eventName, sessionId);
|
||||||
|
this.participant = participant;
|
||||||
|
this.startTime = this.timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CDREvent(String eventName, Participant participant, String sessionId, MediaOptions mediaOptions,
|
||||||
|
String receivingFrom, Long startTime) {
|
||||||
|
this(eventName, sessionId);
|
||||||
|
this.participant = participant;
|
||||||
|
this.mediaOptions = mediaOptions;
|
||||||
|
this.receivingFrom = receivingFrom;
|
||||||
|
this.startTime = startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MediaOptions getMediaOptions() {
|
||||||
|
return mediaOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParticipantPublicId() {
|
||||||
|
return this.participant.getParticipantPublicId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReceivingFrom() {
|
||||||
|
return this.receivingFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public String toString() {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put("sessionId", this.sessionId);
|
||||||
|
json.put("timestamp", this.timeStamp);
|
||||||
|
|
||||||
|
if (this.participant != null) {
|
||||||
|
json.put("participantId", this.participant.getParticipantPublicId());
|
||||||
|
}
|
||||||
|
if (this.mediaOptions != null) {
|
||||||
|
json.put("connection", this.receivingFrom != null ? "INBOUND" : "OUTBOUND");
|
||||||
|
json.put("audioEnabled", this.mediaOptions.audioActive);
|
||||||
|
json.put("videoEnabled", this.mediaOptions.videoActive);
|
||||||
|
if (this.mediaOptions.videoActive) {
|
||||||
|
json.put("videoSource", this.mediaOptions.typeOfVideo);
|
||||||
|
}
|
||||||
|
if (this.receivingFrom != null) {
|
||||||
|
json.put("receivingFrom", this.receivingFrom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.duration != null) {
|
||||||
|
json.put("startTime", this.startTime);
|
||||||
|
json.put("endTime", this.timeStamp);
|
||||||
|
json.put("duration", (this.timeStamp - this.startTime) / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject root = new JSONObject();
|
||||||
|
root.put(this.eventName, json);
|
||||||
|
|
||||||
|
return root.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(CDREvent other) {
|
||||||
|
if (this.participant.equals(other.participant)) {
|
||||||
|
if (this.receivingFrom != null && other.receivingFrom != null) {
|
||||||
|
if (this.receivingFrom.equals(other.receivingFrom)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.receivingFrom == null && other.receivingFrom == null) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,96 +0,0 @@
|
||||||
package io.openvidu.server.cdr;
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import io.openvidu.server.core.MediaOptions;
|
|
||||||
import io.openvidu.server.core.Participant;
|
|
||||||
|
|
||||||
public class CDRTransmission implements Comparable<CDRTransmission> {
|
|
||||||
|
|
||||||
private Participant participant;
|
|
||||||
private String sessionId;
|
|
||||||
private MediaOptions mediaOptions;
|
|
||||||
private Long timeOfStart;
|
|
||||||
private Long timeOfEnd;
|
|
||||||
private CDRTransmission receivingFrom;
|
|
||||||
|
|
||||||
private SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd yyyy, HH:mm:ss");
|
|
||||||
|
|
||||||
public CDRTransmission(Participant participant, String sessionId, MediaOptions mediaOptions, CDRTransmission receivingFrom) {
|
|
||||||
this.participant = participant;
|
|
||||||
this.sessionId = sessionId;
|
|
||||||
this.mediaOptions = mediaOptions;
|
|
||||||
this.receivingFrom = receivingFrom;
|
|
||||||
this.timeOfStart = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Participant getParticipant() {
|
|
||||||
return this.participant;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSessionId() {
|
|
||||||
return this.sessionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MediaOptions getMediaOptions() {
|
|
||||||
return this.mediaOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void endCall() {
|
|
||||||
this.timeOfEnd = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDateOfStart() {
|
|
||||||
return this.dateFormat.format(new Date(this.timeOfStart));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDateOfEnd() {
|
|
||||||
return this.dateFormat.format(new Date(this.timeOfEnd));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int totalCallDuration() {
|
|
||||||
return (int) ((this.timeOfEnd - this.timeOfStart) / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getAudioEnabled() {
|
|
||||||
return this.mediaOptions.audioActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getVideoEnabled() {
|
|
||||||
return this.mediaOptions.videoActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String typeOfVideo() {
|
|
||||||
if (!this.mediaOptions.videoActive) {
|
|
||||||
return "VIDEO_NOT_ENABLED";
|
|
||||||
} else {
|
|
||||||
return this.mediaOptions.typeOfVideo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CDRTransmission getReceivingFrom() {
|
|
||||||
return this.receivingFrom;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(CDRTransmission other) {
|
|
||||||
if (this.participant.equals(other.participant)) {
|
|
||||||
if (this.receivingFrom != null && other.receivingFrom != null) {
|
|
||||||
if (this.receivingFrom.getParticipant().equals(other.receivingFrom.getParticipant())) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.receivingFrom == null && other.receivingFrom == null) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -32,41 +32,67 @@ public class CallDetailRecord {
|
||||||
|
|
||||||
private Logger log = LoggerFactory.getLogger(CallDetailRecord.class);
|
private Logger log = LoggerFactory.getLogger(CallDetailRecord.class);
|
||||||
|
|
||||||
private Map<String, CDRTransmission> publications = new ConcurrentHashMap<>();
|
private Map<String, CDREvent> sessions = new ConcurrentHashMap<>();
|
||||||
private Map<String, Set<CDRTransmission>> subscriptions = new ConcurrentHashMap<>();
|
private Map<String, CDREvent> participants = new ConcurrentHashMap<>();
|
||||||
|
private Map<String, CDREvent> publications = new ConcurrentHashMap<>();
|
||||||
|
private Map<String, Set<CDREvent>> subscriptions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public void recordSessionCreated(String sessionId) {
|
||||||
|
CDREvent e = new CDREvent(CDREvent.SESSION_CREATED, sessionId);
|
||||||
|
this.sessions.put(sessionId, e);
|
||||||
|
log.info("{}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void recordSessionDestroyed(String sessionId) {
|
||||||
|
CDREvent e = this.sessions.remove(sessionId);
|
||||||
|
log.info("{}", new CDREvent(CDREvent.SESSION_DESTROYED, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void recordParticipantJoined(Participant participant, String sessionId) {
|
||||||
|
CDREvent e = new CDREvent(CDREvent.PARTICIPANT_JOINED, participant, sessionId);
|
||||||
|
this.participants.put(participant.getParticipantPublicId(), e);
|
||||||
|
log.info("{}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void recordParticipantLeft(Participant participant, String sessionId) {
|
||||||
|
CDREvent e = this.participants.remove(participant.getParticipantPublicId());
|
||||||
|
log.info("{}", new CDREvent(CDREvent.PARTICIPANT_LEFT, e));
|
||||||
|
}
|
||||||
|
|
||||||
public void recordNewPublisher(Participant participant, String sessionId, MediaOptions mediaOptions) {
|
public void recordNewPublisher(Participant participant, String sessionId, MediaOptions mediaOptions) {
|
||||||
CDRTransmission publisher = new CDRTransmission(participant, sessionId, mediaOptions, null);
|
CDREvent publisher = new CDREvent(CDREvent.CONNECTION_CREATED, participant, sessionId, mediaOptions, null, System.currentTimeMillis());
|
||||||
this.publications.put(participant.getParticipantPublicId(), publisher);
|
this.publications.put(participant.getParticipantPublicId(), publisher);
|
||||||
|
log.info("{}", publisher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void recordNewSubscriber(Participant participant, String sessionId, String senderPublicId) {
|
public void recordNewSubscriber(Participant participant, String sessionId, String senderPublicId) {
|
||||||
CDRTransmission publisher = this.publications.get(senderPublicId);
|
CDREvent publisher = this.publications.get(senderPublicId);
|
||||||
CDRTransmission subscriber = new CDRTransmission(participant, sessionId, publisher.getMediaOptions(), publisher);
|
CDREvent subscriber = new CDREvent(CDREvent.CONNECTION_CREATED, participant, sessionId, publisher.getMediaOptions(), publisher.getParticipantPublicId(), System.currentTimeMillis());
|
||||||
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);
|
||||||
|
log.info("{}", subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean stopPublisher(String participantPublicId) {
|
public boolean stopPublisher(String participantPublicId) {
|
||||||
CDRTransmission publisher = this.publications.remove(participantPublicId);
|
CDREvent publisher = this.publications.remove(participantPublicId);
|
||||||
if (publisher != null) {
|
if (publisher != null) {
|
||||||
publisher.endCall();
|
publisher = new CDREvent(CDREvent.CONNECTION_DESTROYED, publisher);
|
||||||
log.info("{}", getTransmissionMessage(publisher));
|
log.info("{}", publisher);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean stopSubscriber(String participantPublicId, String senderPublicId) {
|
public boolean stopSubscriber(String participantPublicId, String senderPublicId) {
|
||||||
Set<CDRTransmission> participantSubscriptions = this.subscriptions.get(participantPublicId);
|
Set<CDREvent> participantSubscriptions = this.subscriptions.get(participantPublicId);
|
||||||
if (participantSubscriptions != null) {
|
if (participantSubscriptions != null) {
|
||||||
CDRTransmission subscription;
|
CDREvent subscription;
|
||||||
for (Iterator<CDRTransmission> it = participantSubscriptions.iterator(); it.hasNext();) {
|
for (Iterator<CDREvent> it = participantSubscriptions.iterator(); it.hasNext();) {
|
||||||
subscription = it.next();
|
subscription = it.next();
|
||||||
if (subscription.getReceivingFrom().getParticipant().getParticipantPublicId().equals(senderPublicId)) {
|
if (subscription.getReceivingFrom().equals(senderPublicId)) {
|
||||||
it.remove();
|
it.remove();
|
||||||
subscription.endCall();
|
subscription = new CDREvent(CDREvent.CONNECTION_DESTROYED, subscription);
|
||||||
log.info("{}", getTransmissionMessage(subscription));
|
log.info("{}", subscription);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,35 +101,16 @@ public class CallDetailRecord {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopAllSubscriptions(String participantPublicId) {
|
public void stopAllSubscriptions(String participantPublicId) {
|
||||||
Set<CDRTransmission> participantSubscriptions = this.subscriptions.get(participantPublicId);
|
Set<CDREvent> participantSubscriptions = this.subscriptions.get(participantPublicId);
|
||||||
if (participantSubscriptions != null) {
|
if (participantSubscriptions != null) {
|
||||||
CDRTransmission subscription;
|
CDREvent subscription;
|
||||||
for (Iterator<CDRTransmission> it = participantSubscriptions.iterator(); it.hasNext();) {
|
for (Iterator<CDREvent> it = participantSubscriptions.iterator(); it.hasNext();) {
|
||||||
subscription = it.next();
|
subscription = it.next();
|
||||||
subscription.endCall();
|
subscription = new CDREvent(CDREvent.CONNECTION_DESTROYED, subscription);
|
||||||
log.info("{}", getTransmissionMessage(subscription));
|
log.info("{}", subscription);
|
||||||
}
|
}
|
||||||
this.subscriptions.remove(participantPublicId).clear();
|
this.subscriptions.remove(participantPublicId).clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTransmissionMessage(CDRTransmission cdr) {
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
sb.append("<participant>\n");
|
|
||||||
sb.append("\t<id>").append(cdr.getParticipant().getParticipantPublicId()).append("</id>\n");
|
|
||||||
sb.append("\t<session>").append(cdr.getSessionId()).append("</session>\n");
|
|
||||||
sb.append("\t<connection>").append((cdr.getReceivingFrom() != null) ? "INBOUND" : "OUTBOUND").append("</connection>\n");
|
|
||||||
if (cdr.getReceivingFrom() != null) sb.append("\t<from>").append((cdr.getReceivingFrom() != null)
|
|
||||||
? cdr.getReceivingFrom().getParticipant().getParticipantPublicId()
|
|
||||||
: "").append("</from>\n");
|
|
||||||
sb.append("\t<audio-enabled>").append(cdr.getAudioEnabled()).append("</audio-enabled>\n");
|
|
||||||
sb.append("\t<video-enabled>").append(cdr.getVideoEnabled()).append("</video-enabled>\n");
|
|
||||||
if (cdr.getVideoEnabled()) sb.append("\t<videosource>").append(cdr.typeOfVideo()).append("</videosource>\n");
|
|
||||||
sb.append("\t<start-time>").append(cdr.getDateOfStart()).append("</start-time>\n");
|
|
||||||
sb.append("\t<end-time>").append(cdr.getDateOfEnd()).append("</end-time>\n");
|
|
||||||
sb.append("\t<duration>").append(cdr.totalCallDuration()).append("</duration>\n");
|
|
||||||
sb.append("</participant>\n");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ public interface Session {
|
||||||
|
|
||||||
void leave(String participantPrivateId);
|
void leave(String participantPrivateId);
|
||||||
|
|
||||||
void close();
|
boolean close();
|
||||||
|
|
||||||
boolean isClosed();
|
boolean isClosed();
|
||||||
|
|
||||||
|
|
|
@ -33,17 +33,20 @@ public class SessionEventsHandler {
|
||||||
@Autowired
|
@Autowired
|
||||||
protected OpenviduConfig openviduConfig;
|
protected OpenviduConfig openviduConfig;
|
||||||
|
|
||||||
public void onSessionClosed(String sessionId, Set<Participant> participants) {
|
public void onSessionCreated(String sessionId) {
|
||||||
JsonObject notifParams = new JsonObject();
|
if (openviduConfig.isCdrEnabled()) {
|
||||||
notifParams.addProperty(ProtocolElements.ROOMCLOSED_ROOM_PARAM, sessionId);
|
CDR.recordSessionCreated(sessionId);
|
||||||
for (Participant participant : participants) {
|
|
||||||
rpcNotificationService.sendNotification(participant.getParticipantPrivateId(),
|
|
||||||
ProtocolElements.ROOMCLOSED_METHOD, notifParams);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onParticipantJoined(Participant participant, Integer transactionId,
|
public void onSessionClosed(String sessionId) {
|
||||||
Set<Participant> existingParticipants, OpenViduException error) {
|
if (openviduConfig.isCdrEnabled()) {
|
||||||
|
CDR.recordSessionDestroyed(sessionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onParticipantJoined(Participant participant, String sessionId,
|
||||||
|
Set<Participant> existingParticipants, Integer transactionId, OpenViduException error) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||||
return;
|
return;
|
||||||
|
@ -97,10 +100,14 @@ public class SessionEventsHandler {
|
||||||
result.add("value", resultArray);
|
result.add("value", resultArray);
|
||||||
|
|
||||||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result);
|
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result);
|
||||||
|
|
||||||
|
if (openviduConfig.isCdrEnabled()) {
|
||||||
|
CDR.recordParticipantJoined(participant, sessionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onParticipantLeft(Participant participant, Integer transactionId,
|
public void onParticipantLeft(Participant participant, String sessionId,
|
||||||
Set<Participant> remainingParticipants, OpenViduException error) {
|
Set<Participant> remainingParticipants, Integer transactionId, OpenViduException error) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||||
return;
|
return;
|
||||||
|
@ -130,10 +137,14 @@ public class SessionEventsHandler {
|
||||||
}
|
}
|
||||||
rpcNotificationService.closeRpcSession(participant.getParticipantPrivateId());
|
rpcNotificationService.closeRpcSession(participant.getParticipantPrivateId());
|
||||||
|
|
||||||
|
if (openviduConfig.isCdrEnabled()) {
|
||||||
|
CDR.recordParticipantLeft(participant, sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPublishMedia(Participant participant, String sessionId, Integer transactionId, MediaOptions mediaOptions,
|
}
|
||||||
String sdpAnswer, Set<Participant> participants, OpenViduException error) {
|
|
||||||
|
public void onPublishMedia(Participant participant, String sessionId, MediaOptions mediaOptions,
|
||||||
|
String sdpAnswer, Set<Participant> participants, Integer transactionId, OpenViduException error) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -31,30 +31,22 @@ public abstract class SessionManager {
|
||||||
|
|
||||||
private volatile boolean closed = false;
|
private volatile boolean closed = false;
|
||||||
|
|
||||||
public void joinRoom(Participant participant, String sessionId, Integer transactionId) {
|
public abstract void joinRoom(Participant participant, String sessionId, Integer transactionId);
|
||||||
}
|
|
||||||
|
|
||||||
public void leaveRoom(Participant participant, Integer transactionId) {
|
public abstract void leaveRoom(Participant participant, Integer transactionId);
|
||||||
}
|
|
||||||
|
|
||||||
public void publishVideo(Participant participant, MediaOptions mediaOptions, Integer transactionId) {
|
public abstract void publishVideo(Participant participant, MediaOptions mediaOptions, Integer transactionId);
|
||||||
}
|
|
||||||
|
|
||||||
public void unpublishVideo(Participant participant, Integer transactionId) {
|
public abstract void unpublishVideo(Participant participant, Integer transactionId);
|
||||||
}
|
|
||||||
|
|
||||||
public void subscribe(Participant participant, String senderName, String sdpOffer, Integer transactionId) {
|
public abstract void subscribe(Participant participant, String senderName, String sdpOffer, Integer transactionId);
|
||||||
}
|
|
||||||
|
|
||||||
public void unsubscribe(Participant participant, String senderName, Integer transactionId) {
|
public abstract void unsubscribe(Participant participant, String senderName, Integer transactionId);
|
||||||
}
|
|
||||||
|
|
||||||
public void sendMessage(Participant participant, String message, Integer transactionId) {
|
public abstract void sendMessage(Participant participant, String message, Integer transactionId);
|
||||||
}
|
|
||||||
|
|
||||||
public void onIceCandidate(Participant participant, String endpointName, String candidate, int sdpMLineIndex,
|
public abstract void onIceCandidate(Participant participant, String endpointName, String candidate,
|
||||||
String sdpMid, Integer transactionId) {
|
int sdpMLineIndex, String sdpMid, Integer transactionId);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application-originated request to remove a participant from a session. <br/>
|
* Application-originated request to remove a participant from a session. <br/>
|
||||||
|
@ -200,7 +192,8 @@ public abstract class SessionManager {
|
||||||
public boolean isPublisherInSession(String sessionId, Participant participant) {
|
public boolean isPublisherInSession(String sessionId, Participant participant) {
|
||||||
if (!this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
if (!this.isInsecureParticipant(participant.getParticipantPrivateId())) {
|
||||||
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
|
||||||
return ParticipantRole.PUBLISHER.equals(participant.getToken().getRole());
|
return (ParticipantRole.PUBLISHER.equals(participant.getToken().getRole())
|
||||||
|
|| ParticipantRole.MODERATOR.equals(participant.getToken().getRole()));
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -272,8 +265,6 @@ public abstract class SessionManager {
|
||||||
log.info("<SESSIONID, PARTICIPANTS>: {}", this.sessionidParticipantpublicidParticipant.toString());
|
log.info("<SESSIONID, PARTICIPANTS>: {}", this.sessionidParticipantpublicidParticipant.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes all resources. This method has been annotated with the @PreDestroy
|
* Closes all resources. This method has been annotated with the @PreDestroy
|
||||||
* directive (javax.annotation package) so that it will be automatically called
|
* directive (javax.annotation package) so that it will be automatically called
|
||||||
|
@ -298,11 +289,11 @@ public abstract class SessionManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes an existing session by releasing all resources that were allocated for
|
* Closes an existing session by releasing all resources that were allocated for
|
||||||
* it. Once closed, the session can be reopened (will be empty and it will
|
* it. Once closed, the session can be reopened (will be empty and it will use
|
||||||
* use another Media Pipeline). Existing participants will be evicted. <br/>
|
* another Media Pipeline). Existing participants will be evicted. <br/>
|
||||||
* <strong>Dev advice:</strong> The session event handler should send notifications
|
* <strong>Dev advice:</strong> The session event handler should send
|
||||||
* to the existing participants in the session to inform that it was forcibly
|
* notifications to the existing participants in the session to inform that it
|
||||||
* closed.
|
* was forcibly closed.
|
||||||
*
|
*
|
||||||
* @param sessionId
|
* @param sessionId
|
||||||
* identifier of the session
|
* identifier of the session
|
||||||
|
@ -322,9 +313,7 @@ public abstract class SessionManager {
|
||||||
}
|
}
|
||||||
Set<Participant> participants = getParticipants(sessionId);
|
Set<Participant> participants = getParticipants(sessionId);
|
||||||
// copy the ids as they will be removed from the map
|
// copy the ids as they will be removed from the map
|
||||||
Set<String> pids = participants.stream()
|
Set<String> pids = participants.stream().map(Participant::getParticipantPrivateId).collect(Collectors.toSet());
|
||||||
.map(Participant::getParticipantPrivateId)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
for (String pid : pids) {
|
for (String pid : pids) {
|
||||||
try {
|
try {
|
||||||
session.leave(pid);
|
session.leave(pid);
|
||||||
|
|
|
@ -155,7 +155,7 @@ public class KurentoSession implements Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public boolean close() {
|
||||||
if (!closed) {
|
if (!closed) {
|
||||||
|
|
||||||
for (KurentoParticipant participant : participants.values()) {
|
for (KurentoParticipant participant : participants.values()) {
|
||||||
|
@ -174,8 +174,10 @@ public class KurentoSession implements Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.closed = true;
|
this.closed = true;
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
log.warn("Closing an already closed session '{}'", this.sessionId);
|
log.warn("Closing an already closed session '{}'", this.sessionId);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,10 +68,10 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
} 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);
|
||||||
sessionHandler.onParticipantJoined(participant, transactionId, null, e);
|
sessionHandler.onParticipantJoined(participant, sessionId, null, transactionId, e);
|
||||||
}
|
}
|
||||||
if (existingParticipants != null) {
|
if (existingParticipants != null) {
|
||||||
sessionHandler.onParticipantJoined(participant, transactionId, existingParticipants, null);
|
sessionHandler.onParticipantJoined(participant, sessionId, existingParticipants, transactionId, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,9 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
}
|
}
|
||||||
if (remainingParticipants.isEmpty()) {
|
if (remainingParticipants.isEmpty()) {
|
||||||
log.debug("No more participants in session '{}', removing it and closing it", sessionId);
|
log.debug("No more participants in session '{}', removing it and closing it", sessionId);
|
||||||
session.close();
|
if (session.close()) {
|
||||||
|
sessionHandler.onSessionClosed(sessionId);
|
||||||
|
}
|
||||||
sessions.remove(sessionId);
|
sessions.remove(sessionId);
|
||||||
|
|
||||||
sessionidParticipantpublicidParticipant.remove(sessionId);
|
sessionidParticipantpublicidParticipant.remove(sessionId);
|
||||||
|
@ -130,7 +132,7 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
log.warn("Session '{}' removed and closed", sessionId);
|
log.warn("Session '{}' removed and closed", sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionHandler.onParticipantLeft(participant, transactionId, remainingParticipants, null);
|
sessionHandler.onParticipantLeft(participant, sessionId, remainingParticipants, transactionId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,7 +192,7 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
OpenViduException e = new OpenViduException(Code.MEDIA_SDP_ERROR_CODE,
|
OpenViduException e = new OpenViduException(Code.MEDIA_SDP_ERROR_CODE,
|
||||||
"Error generating SDP response for publishing user " + participant.getParticipantPublicId());
|
"Error generating SDP response for publishing user " + participant.getParticipantPublicId());
|
||||||
log.error("PARTICIPANT {}: Error publishing media", participant.getParticipantPublicId(), e);
|
log.error("PARTICIPANT {}: Error publishing media", participant.getParticipantPublicId(), e);
|
||||||
sessionHandler.onPublishMedia(participant, session.getSessionId(), transactionId, mediaOptions, sdpAnswer, participants, e);
|
sessionHandler.onPublishMedia(participant, session.getSessionId(), mediaOptions, sdpAnswer, participants, transactionId, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
session.newPublisher(participant);
|
session.newPublisher(participant);
|
||||||
|
@ -202,7 +204,7 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
participants = kurentoParticipant.getSession().getParticipants();
|
participants = kurentoParticipant.getSession().getParticipants();
|
||||||
|
|
||||||
if (sdpAnswer != null) {
|
if (sdpAnswer != null) {
|
||||||
sessionHandler.onPublishMedia(participant, session.getSessionId(), transactionId, mediaOptions, sdpAnswer, participants, null);
|
sessionHandler.onPublishMedia(participant, session.getSessionId(), mediaOptions, sdpAnswer, participants, transactionId, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,6 +359,8 @@ public class KurentoSessionManager extends SessionManager {
|
||||||
kcName = kurentoClient.getServerManager().getName();
|
kcName = kurentoClient.getServerManager().getName();
|
||||||
}
|
}
|
||||||
log.warn("No session '{}' exists yet. Created one using KurentoClient '{}'.", sessionId, kcName);
|
log.warn("No session '{}' exists yet. Created one using KurentoClient '{}'.", sessionId, kcName);
|
||||||
|
|
||||||
|
sessionHandler.onSessionCreated(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
log4j.rootLogger=INFO, stdout
|
|
||||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
|
||||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
|
||||||
log4j.appender.stdout.layout.ConversionPattern=[%p] %d [%.12t] %c (%M) - %m%n
|
|
||||||
|
|
||||||
log4j.logger.io.openvidu.server.cdr.CallDetailRecord=INFO, cdr
|
|
||||||
log4j.appender.cdr=org.apache.log4j.DailyRollingFileAppender
|
|
||||||
log4j.appender.cdr.File=log/CDR.log
|
|
||||||
log4j.appender.cdr.layout=org.apache.log4j.PatternLayout
|
|
||||||
log4j.appender.cdr.layout.ConversionPattern=%m\n
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<timestamp key="myTimestamp" timeReference="contextBirth" datePattern="HH-mm-ss"/>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||||
|
<Pattern>[%p] %d [%.12t] %c \(%M\) - %msg%n</Pattern>
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
<appender name="CDR"
|
||||||
|
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<FileNamePattern>log/CDR.%d{yyyy-MM-dd}_${myTimestamp}.log</FileNamePattern>
|
||||||
|
<MaxHistory>30</MaxHistory>
|
||||||
|
<TotalSizeCap>20GB</TotalSizeCap>
|
||||||
|
</rollingPolicy>
|
||||||
|
<layout>
|
||||||
|
<pattern>%m\n</pattern>
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
<logger name="io.openvidu.server.cdr.CallDetailRecord">
|
||||||
|
<level value="INFO" />
|
||||||
|
<appender-ref ref="CDR" />
|
||||||
|
</logger>
|
||||||
|
<root>
|
||||||
|
<level value="INFO" />
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
Loading…
Reference in New Issue