mirror of https://github.com/OpenVidu/openvidu.git
CDR system
parent
b0d3db2de3
commit
33e4009545
|
@ -37,11 +37,12 @@ import com.google.gson.JsonArray;
|
|||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import io.openvidu.server.cdr.CallDetailRecord;
|
||||
import io.openvidu.server.config.OpenviduConfig;
|
||||
import io.openvidu.server.core.SessionManager;
|
||||
import io.openvidu.server.kurento.AutodiscoveryKurentoClientProvider;
|
||||
import io.openvidu.server.kurento.KurentoClientProvider;
|
||||
import io.openvidu.server.kurento.core.KurentoSessionHandler;
|
||||
import io.openvidu.server.kurento.core.KurentoSessionEventsHandler;
|
||||
import io.openvidu.server.kurento.core.KurentoSessionManager;
|
||||
import io.openvidu.server.kurento.kms.FixedOneKmsManager;
|
||||
import io.openvidu.server.rest.NgrokRestController;
|
||||
|
@ -111,8 +112,14 @@ public class OpenViduServer implements JsonRpcConfigurer {
|
|||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public KurentoSessionHandler kurentoSessionHandler() {
|
||||
return new KurentoSessionHandler();
|
||||
public KurentoSessionEventsHandler kurentoSessionEventsHandler() {
|
||||
return new KurentoSessionEventsHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public CallDetailRecord cdr() {
|
||||
return new CallDetailRecord();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package io.openvidu.server.cdr;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import io.openvidu.server.core.MediaOptions;
|
||||
import io.openvidu.server.core.Participant;
|
||||
|
||||
/**
|
||||
* CDR logger to register all information of each WebRTC connection:
|
||||
*
|
||||
* - Participant unique identifier
|
||||
* - Session unique identifier
|
||||
* - Inbound or Outbound WebRTC connection
|
||||
* - <if inbound connection> Sender unique identifier
|
||||
* - Audio media stream enabled
|
||||
* - Video media stream enabled
|
||||
* - <if Video media stream enabled> Video source [CAMERA, SCREEN]
|
||||
* - Time of start of the call
|
||||
* - Time of end of the call
|
||||
* - Total time duration
|
||||
*
|
||||
* @author Pablo Fuente (pablofuenteperez@gmail.com)
|
||||
*/
|
||||
public class CallDetailRecord {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(CallDetailRecord.class);
|
||||
|
||||
private Map<String, CDRTransmission> publications = new ConcurrentHashMap<>();
|
||||
private Map<String, Set<CDRTransmission>> subscriptions = new ConcurrentHashMap<>();
|
||||
|
||||
public void recordNewPublisher(Participant participant, String sessionId, MediaOptions mediaOptions) {
|
||||
CDRTransmission publisher = new CDRTransmission(participant, sessionId, mediaOptions, null);
|
||||
this.publications.put(participant.getParticipantPublicId(), publisher);
|
||||
}
|
||||
|
||||
public void recordNewSubscriber(Participant participant, String sessionId, String senderPublicId) {
|
||||
CDRTransmission publisher = this.publications.get(senderPublicId);
|
||||
CDRTransmission subscriber = new CDRTransmission(participant, sessionId, publisher.getMediaOptions(), publisher);
|
||||
this.subscriptions.putIfAbsent(participant.getParticipantPublicId(), new ConcurrentSkipListSet<>());
|
||||
this.subscriptions.get(participant.getParticipantPublicId()).add(subscriber);
|
||||
}
|
||||
|
||||
public boolean stopPublisher(String participantPublicId) {
|
||||
CDRTransmission publisher = this.publications.remove(participantPublicId);
|
||||
if (publisher != null) {
|
||||
publisher.endCall();
|
||||
log.info("{}", getTransmissionMessage(publisher));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean stopSubscriber(String participantPublicId, String senderPublicId) {
|
||||
Set<CDRTransmission> participantSubscriptions = this.subscriptions.get(participantPublicId);
|
||||
if (participantSubscriptions != null) {
|
||||
CDRTransmission subscription;
|
||||
for (Iterator<CDRTransmission> it = participantSubscriptions.iterator(); it.hasNext();) {
|
||||
subscription = it.next();
|
||||
if (subscription.getReceivingFrom().getParticipant().getParticipantPublicId().equals(senderPublicId)) {
|
||||
it.remove();
|
||||
subscription.endCall();
|
||||
log.info("{}", getTransmissionMessage(subscription));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void stopAllSubscriptions(String participantPublicId) {
|
||||
Set<CDRTransmission> participantSubscriptions = this.subscriptions.get(participantPublicId);
|
||||
if (participantSubscriptions != null) {
|
||||
CDRTransmission subscription;
|
||||
for (Iterator<CDRTransmission> it = participantSubscriptions.iterator(); it.hasNext();) {
|
||||
subscription = it.next();
|
||||
subscription.endCall();
|
||||
log.info("{}", getTransmissionMessage(subscription));
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
|
@ -14,6 +14,9 @@ public class OpenviduConfig {
|
|||
|
||||
@Value("${openvidu.secret}")
|
||||
private String openviduSecret;
|
||||
|
||||
@Value("${openvidu.cdr}")
|
||||
private boolean openviduCdr;
|
||||
|
||||
public String getOpenViduPublicUrl() {
|
||||
return this.openviduPublicUrl;
|
||||
|
@ -30,5 +33,9 @@ public class OpenviduConfig {
|
|||
public boolean isOpenViduSecret(String secret) {
|
||||
return secret.equals(this.getOpenViduSecret());
|
||||
}
|
||||
|
||||
public boolean isCdrEnabled() {
|
||||
return this.openviduCdr;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,9 +17,6 @@ public class Participant {
|
|||
|
||||
private final String METADATA_SEPARATOR = "%/%";
|
||||
|
||||
public Participant() {
|
||||
}
|
||||
|
||||
public Participant(String participantPrivatetId, String participantPublicId, Token token, String clientMetadata) {
|
||||
this.participantPrivatetId = participantPrivatetId;
|
||||
this.participantPublicId = participantPublicId;
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package io.openvidu.server.kurento.core;
|
||||
package io.openvidu.server.core;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.kurento.client.IceCandidate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
|
@ -15,21 +14,24 @@ import com.google.gson.JsonObject;
|
|||
import io.openvidu.client.OpenViduException;
|
||||
import io.openvidu.client.OpenViduException.Code;
|
||||
import io.openvidu.client.internal.ProtocolElements;
|
||||
import io.openvidu.server.cdr.CallDetailRecord;
|
||||
import io.openvidu.server.config.InfoHandler;
|
||||
import io.openvidu.server.core.MediaOptions;
|
||||
import io.openvidu.server.core.Participant;
|
||||
import io.openvidu.server.config.OpenviduConfig;
|
||||
import io.openvidu.server.rpc.RpcNotificationService;
|
||||
|
||||
public class KurentoSessionHandler {
|
||||
public class SessionEventsHandler {
|
||||
|
||||
@Autowired
|
||||
private RpcNotificationService rpcNotificationService;
|
||||
protected RpcNotificationService rpcNotificationService;
|
||||
|
||||
@Autowired
|
||||
private InfoHandler infoHandler;
|
||||
protected InfoHandler infoHandler;
|
||||
|
||||
public KurentoSessionHandler() {
|
||||
}
|
||||
@Autowired
|
||||
protected CallDetailRecord CDR;
|
||||
|
||||
@Autowired
|
||||
protected OpenviduConfig openviduConfig;
|
||||
|
||||
public void onSessionClosed(String sessionId, Set<Participant> participants) {
|
||||
JsonObject notifParams = new JsonObject();
|
||||
|
@ -103,12 +105,22 @@ public class KurentoSessionHandler {
|
|||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isPublishing = false;
|
||||
if (openviduConfig.isCdrEnabled()) {
|
||||
isPublishing = CDR.stopPublisher(participant.getParticipantPublicId());
|
||||
CDR.stopAllSubscriptions(participant.getParticipantPublicId());
|
||||
}
|
||||
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(ProtocolElements.PARTICIPANTLEFT_NAME_PARAM, participant.getParticipantPublicId());
|
||||
for (Participant p : remainingParticipants) {
|
||||
rpcNotificationService.sendNotification(p.getParticipantPrivateId(),
|
||||
ProtocolElements.PARTICIPANTLEFT_METHOD, params);
|
||||
|
||||
if (isPublishing && openviduConfig.isCdrEnabled()) {
|
||||
CDR.stopSubscriber(p.getParticipantPublicId(), participant.getParticipantPublicId());
|
||||
}
|
||||
}
|
||||
|
||||
if (transactionId != null) {
|
||||
|
@ -117,9 +129,10 @@ public class KurentoSessionHandler {
|
|||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
|
||||
}
|
||||
rpcNotificationService.closeRpcSession(participant.getParticipantPrivateId());
|
||||
|
||||
}
|
||||
|
||||
public void onPublishMedia(Participant participant, Integer transactionId, MediaOptions mediaOptions,
|
||||
public void onPublishMedia(Participant participant, String sessionId, Integer transactionId, MediaOptions mediaOptions,
|
||||
String sdpAnswer, Set<Participant> participants, OpenViduException error) {
|
||||
if (error != null) {
|
||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||
|
@ -160,17 +173,42 @@ public class KurentoSessionHandler {
|
|||
ProtocolElements.PARTICIPANTPUBLISHED_METHOD, params);
|
||||
}
|
||||
}
|
||||
|
||||
if (openviduConfig.isCdrEnabled()) {
|
||||
CDR.recordNewPublisher(participant, sessionId, mediaOptions);
|
||||
}
|
||||
}
|
||||
|
||||
public void onRecvIceCandidate(Participant participant, Integer transactionId, OpenViduException error) {
|
||||
public void onUnpublishMedia(Participant participant, Set<Participant> participants, Integer transactionId,
|
||||
OpenViduException error) {
|
||||
if (error != null) {
|
||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||
return;
|
||||
}
|
||||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
|
||||
|
||||
if (openviduConfig.isCdrEnabled()) {
|
||||
CDR.stopPublisher(participant.getParticipantPublicId());
|
||||
}
|
||||
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(ProtocolElements.PARTICIPANTUNPUBLISHED_NAME_PARAM, participant.getParticipantPublicId());
|
||||
|
||||
for (Participant p : participants) {
|
||||
if (p.getParticipantPrivateId().equals(participant.getParticipantPrivateId())) {
|
||||
continue;
|
||||
} else {
|
||||
rpcNotificationService.sendNotification(p.getParticipantPrivateId(),
|
||||
ProtocolElements.PARTICIPANTUNPUBLISHED_METHOD, params);
|
||||
if (openviduConfig.isCdrEnabled()) {
|
||||
CDR.stopSubscriber(p.getParticipantPublicId(), participant.getParticipantPublicId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSubscribe(Participant participant, String sdpAnswer, Integer transactionId, OpenViduException error) {
|
||||
public void onSubscribe(Participant participant, String sessionId, String senderName, String sdpAnswer, Integer transactionId,
|
||||
OpenViduException error) {
|
||||
if (error != null) {
|
||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||
return;
|
||||
|
@ -178,14 +216,22 @@ public class KurentoSessionHandler {
|
|||
JsonObject result = new JsonObject();
|
||||
result.addProperty(ProtocolElements.RECEIVEVIDEO_SDPANSWER_PARAM, sdpAnswer);
|
||||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result);
|
||||
|
||||
if (openviduConfig.isCdrEnabled()) {
|
||||
CDR.recordNewSubscriber(participant, sessionId, senderName);
|
||||
}
|
||||
}
|
||||
|
||||
public void onUnsubscribe(Participant participant, Integer transactionId, OpenViduException error) {
|
||||
public void onUnsubscribe(Participant participant, String senderName, Integer transactionId, OpenViduException error) {
|
||||
if (error != null) {
|
||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||
return;
|
||||
}
|
||||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
|
||||
|
||||
if (openviduConfig.isCdrEnabled()) {
|
||||
CDR.stopSubscriber(participant.getParticipantPublicId(), senderName);
|
||||
}
|
||||
}
|
||||
|
||||
public void onSendMessage(Participant participant, JsonObject message, Set<Participant> participants,
|
||||
|
@ -238,25 +284,12 @@ public class KurentoSessionHandler {
|
|||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
|
||||
}
|
||||
|
||||
public void onUnpublishMedia(Participant participant, Set<Participant> participants, Integer transactionId,
|
||||
OpenViduException error) {
|
||||
public void onRecvIceCandidate(Participant participant, Integer transactionId, OpenViduException error) {
|
||||
if (error != null) {
|
||||
rpcNotificationService.sendErrorResponse(participant.getParticipantPrivateId(), transactionId, null, error);
|
||||
return;
|
||||
}
|
||||
rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
|
||||
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(ProtocolElements.PARTICIPANTUNPUBLISHED_NAME_PARAM, participant.getParticipantPublicId());
|
||||
|
||||
for (Participant p : participants) {
|
||||
if (p.getParticipantPrivateId().equals(participant.getParticipantPrivateId())) {
|
||||
continue;
|
||||
} else {
|
||||
rpcNotificationService.sendNotification(p.getParticipantPrivateId(),
|
||||
ProtocolElements.PARTICIPANTUNPUBLISHED_METHOD, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onParticipantEvicted(Participant participant) {
|
||||
|
@ -264,41 +297,7 @@ public class KurentoSessionHandler {
|
|||
ProtocolElements.PARTICIPANTEVICTED_METHOD, new JsonObject());
|
||||
}
|
||||
|
||||
// ------------ EVENTS FROM ROOM HANDLER -----
|
||||
|
||||
public void onIceCandidate(String roomName, String participantId, String endpointName, IceCandidate candidate) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(ProtocolElements.ICECANDIDATE_EPNAME_PARAM, endpointName);
|
||||
params.addProperty(ProtocolElements.ICECANDIDATE_SDPMLINEINDEX_PARAM, candidate.getSdpMLineIndex());
|
||||
params.addProperty(ProtocolElements.ICECANDIDATE_SDPMID_PARAM, candidate.getSdpMid());
|
||||
params.addProperty(ProtocolElements.ICECANDIDATE_CANDIDATE_PARAM, candidate.getCandidate());
|
||||
rpcNotificationService.sendNotification(participantId, ProtocolElements.ICECANDIDATE_METHOD, params);
|
||||
}
|
||||
|
||||
public void onPipelineError(String roomName, Set<Participant> participants, String description) {
|
||||
JsonObject notifParams = new JsonObject();
|
||||
notifParams.addProperty(ProtocolElements.MEDIAERROR_ERROR_PARAM, description);
|
||||
for (Participant p : participants) {
|
||||
rpcNotificationService.sendNotification(p.getParticipantPrivateId(), ProtocolElements.MEDIAERROR_METHOD,
|
||||
notifParams);
|
||||
}
|
||||
}
|
||||
|
||||
public void onMediaElementError(String roomName, String participantId, String description) {
|
||||
JsonObject notifParams = new JsonObject();
|
||||
notifParams.addProperty(ProtocolElements.MEDIAERROR_ERROR_PARAM, description);
|
||||
rpcNotificationService.sendNotification(participantId, ProtocolElements.MEDIAERROR_METHOD, notifParams);
|
||||
}
|
||||
|
||||
public void updateFilter(String roomName, Participant participant, String filterId, String state) {
|
||||
}
|
||||
|
||||
public String getNextFilterState(String filterId, String state) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public InfoHandler getInfoHandler() {
|
||||
return this.infoHandler;
|
||||
}
|
||||
|
||||
}
|
|
@ -39,21 +39,21 @@ public abstract class SessionManager {
|
|||
|
||||
public void publishVideo(Participant participant, MediaOptions mediaOptions, Integer transactionId) {
|
||||
}
|
||||
|
||||
public void onIceCandidate(Participant participant, String endpointName, String candidate, int sdpMLineIndex,
|
||||
String sdpMid, Integer transactionId) {
|
||||
|
||||
public void unpublishVideo(Participant participant, Integer transactionId) {
|
||||
}
|
||||
|
||||
|
||||
public void subscribe(Participant participant, String senderName, String sdpOffer, Integer transactionId) {
|
||||
}
|
||||
|
||||
public void unsubscribe(Participant participant, String senderName, Integer transactionId) {
|
||||
}
|
||||
|
||||
|
||||
public void sendMessage(Participant participant, String message, Integer transactionId) {
|
||||
}
|
||||
|
||||
public void unpublishVideo(Participant participant, Integer transactionId) {
|
||||
public void onIceCandidate(Participant participant, String endpointName, String candidate, int sdpMLineIndex,
|
||||
String sdpMid, Integer transactionId) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,7 +37,7 @@ public class KurentoSession implements Session {
|
|||
private CountDownLatch pipelineLatch = new CountDownLatch(1);
|
||||
|
||||
private KurentoClient kurentoClient;
|
||||
private KurentoSessionHandler kurentoSessionHandler;
|
||||
private KurentoSessionEventsHandler kurentoSessionHandler;
|
||||
|
||||
private volatile boolean closed = false;
|
||||
|
||||
|
@ -49,7 +49,7 @@ public class KurentoSession implements Session {
|
|||
private volatile boolean pipelineReleased = false;
|
||||
private boolean destroyKurentoClient;
|
||||
|
||||
public KurentoSession(String sessionId, KurentoClient kurentoClient, KurentoSessionHandler kurentoSessionHandler,
|
||||
public KurentoSession(String sessionId, KurentoClient kurentoClient, KurentoSessionEventsHandler kurentoSessionHandler,
|
||||
boolean destroyKurentoClient) {
|
||||
this.sessionId = sessionId;
|
||||
this.kurentoClient = kurentoClient;
|
||||
|
@ -119,7 +119,7 @@ public class KurentoSession implements Session {
|
|||
KurentoParticipant participant = participants.get(participantPrivateId);
|
||||
if (participant == null) {
|
||||
throw new OpenViduException(Code.USER_NOT_FOUND_ERROR_CODE,
|
||||
"User #" + participantPrivateId + " not found in session '" + sessionId + "'");
|
||||
"Participant with private id " + participantPrivateId + " not found in session '" + sessionId + "'");
|
||||
}
|
||||
participant.releaseAllFilters();
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package io.openvidu.server.kurento.core;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.kurento.client.IceCandidate;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import io.openvidu.client.internal.ProtocolElements;
|
||||
import io.openvidu.server.core.Participant;
|
||||
import io.openvidu.server.core.SessionEventsHandler;
|
||||
|
||||
public class KurentoSessionEventsHandler extends SessionEventsHandler {
|
||||
|
||||
public KurentoSessionEventsHandler() {
|
||||
}
|
||||
|
||||
public void onIceCandidate(String roomName, String participantId, String endpointName, IceCandidate candidate) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty(ProtocolElements.ICECANDIDATE_EPNAME_PARAM, endpointName);
|
||||
params.addProperty(ProtocolElements.ICECANDIDATE_SDPMLINEINDEX_PARAM, candidate.getSdpMLineIndex());
|
||||
params.addProperty(ProtocolElements.ICECANDIDATE_SDPMID_PARAM, candidate.getSdpMid());
|
||||
params.addProperty(ProtocolElements.ICECANDIDATE_CANDIDATE_PARAM, candidate.getCandidate());
|
||||
rpcNotificationService.sendNotification(participantId, ProtocolElements.ICECANDIDATE_METHOD, params);
|
||||
}
|
||||
|
||||
public void onPipelineError(String roomName, Set<Participant> participants, String description) {
|
||||
JsonObject notifParams = new JsonObject();
|
||||
notifParams.addProperty(ProtocolElements.MEDIAERROR_ERROR_PARAM, description);
|
||||
for (Participant p : participants) {
|
||||
rpcNotificationService.sendNotification(p.getParticipantPrivateId(), ProtocolElements.MEDIAERROR_METHOD,
|
||||
notifParams);
|
||||
}
|
||||
}
|
||||
|
||||
public void onMediaElementError(String roomName, String participantId, String description) {
|
||||
JsonObject notifParams = new JsonObject();
|
||||
notifParams.addProperty(ProtocolElements.MEDIAERROR_ERROR_PARAM, description);
|
||||
rpcNotificationService.sendNotification(participantId, ProtocolElements.MEDIAERROR_METHOD, notifParams);
|
||||
}
|
||||
|
||||
public void updateFilter(String roomName, Participant participant, String filterId, String state) {
|
||||
}
|
||||
|
||||
public String getNextFilterState(String filterId, String state) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -36,7 +36,7 @@ public class KurentoSessionManager extends SessionManager {
|
|||
private KurentoClientProvider kcProvider;
|
||||
|
||||
@Autowired
|
||||
private KurentoSessionHandler sessionHandler;
|
||||
private KurentoSessionEventsHandler sessionHandler;
|
||||
|
||||
@Override
|
||||
public synchronized void joinRoom(Participant participant, String sessionId, Integer transactionId) {
|
||||
|
@ -190,7 +190,7 @@ public class KurentoSessionManager extends SessionManager {
|
|||
OpenViduException e = new OpenViduException(Code.MEDIA_SDP_ERROR_CODE,
|
||||
"Error generating SDP response for publishing user " + participant.getParticipantPublicId());
|
||||
log.error("PARTICIPANT {}: Error publishing media", participant.getParticipantPublicId(), e);
|
||||
sessionHandler.onPublishMedia(participant, transactionId, mediaOptions, sdpAnswer, participants, e);
|
||||
sessionHandler.onPublishMedia(participant, session.getSessionId(), transactionId, mediaOptions, sdpAnswer, participants, e);
|
||||
}
|
||||
|
||||
session.newPublisher(participant);
|
||||
|
@ -202,35 +202,44 @@ public class KurentoSessionManager extends SessionManager {
|
|||
participants = kurentoParticipant.getSession().getParticipants();
|
||||
|
||||
if (sdpAnswer != null) {
|
||||
sessionHandler.onPublishMedia(participant, transactionId, mediaOptions, sdpAnswer, participants, null);
|
||||
sessionHandler.onPublishMedia(participant, session.getSessionId(), transactionId, mediaOptions, sdpAnswer, participants, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onIceCandidate(Participant participant, String endpointName, String candidate, int sdpMLineIndex,
|
||||
String sdpMid, Integer transactionId) {
|
||||
public void unpublishVideo(Participant participant, Integer transactionId) {
|
||||
try {
|
||||
KurentoParticipant kParticipant = (KurentoParticipant) participant;
|
||||
log.debug("Request [ICE_CANDIDATE] endpoint={} candidate={} " + "sdpMLineIdx={} sdpMid={} ({})",
|
||||
endpointName, candidate, sdpMLineIndex, sdpMid, participant.getParticipantPublicId());
|
||||
kParticipant.addIceCandidate(endpointName, new IceCandidate(candidate, sdpMid, sdpMLineIndex));
|
||||
sessionHandler.onRecvIceCandidate(participant, transactionId, null);
|
||||
KurentoSession session = kParticipant.getSession();
|
||||
|
||||
log.debug("Request [UNPUBLISH_MEDIA] ({})", participant.getParticipantPublicId());
|
||||
if (!participant.isStreaming()) {
|
||||
throw new OpenViduException(Code.USER_NOT_STREAMING_ERROR_CODE,
|
||||
"Participant '" + participant.getParticipantPublicId() + "' is not streaming media");
|
||||
}
|
||||
kParticipant.unpublishMedia();
|
||||
session.cancelPublisher(participant);
|
||||
|
||||
Set<Participant> participants = session.getParticipants();
|
||||
|
||||
sessionHandler.onUnpublishMedia(participant, participants, transactionId, null);
|
||||
|
||||
} catch (OpenViduException e) {
|
||||
log.error("PARTICIPANT {}: Error receiving ICE " + "candidate (epName={}, candidate={})",
|
||||
participant.getParticipantPublicId(), endpointName, candidate, e);
|
||||
sessionHandler.onRecvIceCandidate(participant, transactionId, e);
|
||||
log.warn("PARTICIPANT {}: Error unpublishing media", participant.getParticipantPublicId(), e);
|
||||
sessionHandler.onUnpublishMedia(participant, null, transactionId, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void subscribe(Participant participant, String senderName, String sdpOffer, Integer transactionId) {
|
||||
String sdpAnswer = null;
|
||||
Session session = null;
|
||||
try {
|
||||
log.debug("Request [SUBSCRIBE] remoteParticipant={} sdpOffer={} ({})", senderName, sdpOffer,
|
||||
participant.getParticipantPublicId());
|
||||
|
||||
KurentoParticipant kParticipant = (KurentoParticipant) participant;
|
||||
Session session = ((KurentoParticipant) participant).getSession();
|
||||
session = ((KurentoParticipant) participant).getSession();
|
||||
Participant senderParticipant = session.getParticipantByPublicId(senderName);
|
||||
|
||||
if (senderParticipant == null) {
|
||||
|
@ -258,10 +267,10 @@ public class KurentoSessionManager extends SessionManager {
|
|||
}
|
||||
} catch (OpenViduException e) {
|
||||
log.error("PARTICIPANT {}: Error subscribing to {}", participant.getParticipantPublicId(), senderName, e);
|
||||
sessionHandler.onSubscribe(participant, null, transactionId, e);
|
||||
sessionHandler.onSubscribe(participant, session.getSessionId(), senderName, null, transactionId, e);
|
||||
}
|
||||
if (sdpAnswer != null) {
|
||||
sessionHandler.onSubscribe(participant, sdpAnswer, transactionId, null);
|
||||
sessionHandler.onSubscribe(participant, session.getSessionId(), senderName, sdpAnswer, transactionId, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +293,7 @@ public class KurentoSessionManager extends SessionManager {
|
|||
|
||||
kParticipant.cancelReceivingMedia(senderName);
|
||||
|
||||
sessionHandler.onUnsubscribe(participant, transactionId, null);
|
||||
sessionHandler.onUnsubscribe(participant, senderName, transactionId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -301,28 +310,22 @@ public class KurentoSessionManager extends SessionManager {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void unpublishVideo(Participant participant, Integer transactionId) {
|
||||
public void onIceCandidate(Participant participant, String endpointName, String candidate, int sdpMLineIndex,
|
||||
String sdpMid, Integer transactionId) {
|
||||
try {
|
||||
KurentoParticipant kParticipant = (KurentoParticipant) participant;
|
||||
KurentoSession session = kParticipant.getSession();
|
||||
|
||||
log.debug("Request [UNPUBLISH_MEDIA] ({})", participant.getParticipantPublicId());
|
||||
if (!participant.isStreaming()) {
|
||||
throw new OpenViduException(Code.USER_NOT_STREAMING_ERROR_CODE,
|
||||
"Participant '" + participant.getParticipantPublicId() + "' is not streaming media");
|
||||
}
|
||||
kParticipant.unpublishMedia();
|
||||
session.cancelPublisher(participant);
|
||||
|
||||
Set<Participant> participants = session.getParticipants();
|
||||
sessionHandler.onUnpublishMedia(participant, participants, transactionId, null);
|
||||
|
||||
log.debug("Request [ICE_CANDIDATE] endpoint={} candidate={} " + "sdpMLineIdx={} sdpMid={} ({})",
|
||||
endpointName, candidate, sdpMLineIndex, sdpMid, participant.getParticipantPublicId());
|
||||
kParticipant.addIceCandidate(endpointName, new IceCandidate(candidate, sdpMid, sdpMLineIndex));
|
||||
sessionHandler.onRecvIceCandidate(participant, transactionId, null);
|
||||
} catch (OpenViduException e) {
|
||||
log.warn("PARTICIPANT {}: Error unpublishing media", participant.getParticipantPublicId(), e);
|
||||
sessionHandler.onUnpublishMedia(participant, null, transactionId, e);
|
||||
log.error("PARTICIPANT {}: Error receiving ICE " + "candidate (epName={}, candidate={})",
|
||||
participant.getParticipantPublicId(), endpointName, candidate, e);
|
||||
sessionHandler.onRecvIceCandidate(participant, transactionId, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a session if it doesn't already exist. The session's id will be
|
||||
* indicated by the session info bean.
|
||||
|
|
|
@ -10,3 +10,4 @@ kms.uris=[\"ws://localhost:8888/kurento\"]
|
|||
|
||||
openvidu.secret: MY_SECRET
|
||||
openvidu.publicurl: local
|
||||
openvidu.cdr: false
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
log4j.rootLogger=info, stdout
|
||||
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.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
|
|
@ -60,7 +60,7 @@ import io.openvidu.client.internal.ProtocolElements;
|
|||
import io.openvidu.client.internal.Notification.Method;
|
||||
import io.openvidu.server.core.Participant;
|
||||
import io.openvidu.server.core.Token;
|
||||
import io.openvidu.server.kurento.core.KurentoSessionHandler;
|
||||
import io.openvidu.server.kurento.core.KurentoSessionEventsHandler;
|
||||
import io.openvidu.server.rpc.RpcConnection;
|
||||
import io.openvidu.server.rpc.RpcHandler;
|
||||
import io.openvidu.server.rpc.RpcNotificationService;
|
||||
|
@ -83,7 +83,7 @@ public class RoomProtocolTest {
|
|||
@Mock
|
||||
private RpcHandler userControl;
|
||||
|
||||
private KurentoSessionHandler sessionHandler;
|
||||
private KurentoSessionEventsHandler sessionHandler;
|
||||
|
||||
private JsonRpcClientLocal localClient0;
|
||||
private OpenViduClient client0;
|
||||
|
|
|
@ -92,7 +92,7 @@ import io.openvidu.server.core.SessionManager;
|
|||
import io.openvidu.server.core.Token;
|
||||
import io.openvidu.server.kurento.KurentoClientProvider;
|
||||
import io.openvidu.server.kurento.KurentoClientSessionInfo;
|
||||
import io.openvidu.server.kurento.core.KurentoSessionHandler;
|
||||
import io.openvidu.server.kurento.core.KurentoSessionEventsHandler;
|
||||
import io.openvidu.server.kurento.core.KurentoSessionManager;
|
||||
|
||||
/**
|
||||
|
@ -126,7 +126,7 @@ public class RoomManagerTest {
|
|||
@Mock
|
||||
private KurentoClientProvider kcProvider;
|
||||
@Mock
|
||||
private KurentoSessionHandler roomHandler;
|
||||
private KurentoSessionEventsHandler roomHandler;
|
||||
|
||||
@Mock
|
||||
private KurentoClient kurentoClient;
|
||||
|
@ -1351,7 +1351,7 @@ public class RoomManagerTest {
|
|||
private Set<Participant> userJoinRoom(final String room, String user, String pid,
|
||||
boolean joinMustSucceed) {
|
||||
return userJoinRoom(room, user, pid, joinMustSucceed, true);
|
||||
}*/
|
||||
}
|
||||
|
||||
private Set<Participant> userJoinRoom(final String room, String user, String pid,
|
||||
boolean joinMustSucceed) {
|
||||
|
@ -1376,5 +1376,5 @@ public class RoomManagerTest {
|
|||
verify(kurentoClient, times(0)).createMediaPipeline(kurentoClientCaptor.capture());
|
||||
|
||||
return existingPeers;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue