mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: webrtcDebug event
parent
f672090757
commit
af57ce747f
|
@ -36,7 +36,7 @@ public class OpenViduException extends JsonRpcErrorException {
|
|||
ROOM_CANNOT_BE_CREATED_ERROR_CODE(204), ROOM_CLOSED_ERROR_CODE(203), ROOM_NOT_FOUND_ERROR_CODE(202),
|
||||
ROOM_GENERIC_ERROR_CODE(201),
|
||||
|
||||
USER_NOT_STREAMING_ERROR_CODE(105), EXISTING_USER_IN_ROOM_ERROR_CODE(104), USER_CLOSED_ERROR_CODE(103),
|
||||
USER_ALREADY_STREAMING_ERROR_CODE(106), USER_NOT_STREAMING_ERROR_CODE(105), EXISTING_USER_IN_ROOM_ERROR_CODE(104), USER_CLOSED_ERROR_CODE(103),
|
||||
USER_NOT_FOUND_ERROR_CODE(102), USER_GENERIC_ERROR_CODE(10),
|
||||
|
||||
USER_UNAUTHORIZED_ERROR_CODE(401), ROLE_NOT_FOUND_ERROR_CODE(402), SESSIONID_CANNOT_BE_CREATED_ERROR_CODE(403),
|
||||
|
|
|
@ -26,6 +26,8 @@ public interface CDRLogger {
|
|||
|
||||
public void log(KmsEvent event);
|
||||
|
||||
public void log(WebrtcDebugEvent event);
|
||||
|
||||
public void log(SessionSummary sessionSummary);
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,10 @@ public class CDRLoggerFile implements CDRLogger {
|
|||
public void log(KmsEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(WebrtcDebugEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(SessionSummary sessionSummary) {
|
||||
}
|
||||
|
|
|
@ -211,6 +211,12 @@ public class CallDetailRecord {
|
|||
});
|
||||
}
|
||||
|
||||
public void log(WebrtcDebugEvent event) {
|
||||
this.loggers.forEach(logger -> {
|
||||
logger.log(event);
|
||||
});
|
||||
}
|
||||
|
||||
public void log(SessionSummary sessionSummary) {
|
||||
this.loggers.forEach(logger -> {
|
||||
logger.log(sessionSummary);
|
||||
|
|
|
@ -6,16 +6,28 @@ import io.openvidu.server.core.Participant;
|
|||
|
||||
public class WebrtcDebugEvent {
|
||||
|
||||
public enum WebrtcDebugEventIssuer {
|
||||
client, server
|
||||
}
|
||||
|
||||
public enum WebrtcDebugEventOperation {
|
||||
publish, subscribe, reconnectPublisher, reconnectSubscriber
|
||||
}
|
||||
|
||||
public enum WebrtcDebugEventType {
|
||||
sdpOffer, sdpOfferMunged, sdpAnswer
|
||||
}
|
||||
|
||||
private Participant participant;
|
||||
private String endpoint;
|
||||
private String issuer; // [client, server]
|
||||
private String operation; // [publish, subscribe, reconnectPublisher, reconnectSubscriber]
|
||||
private String type; // [sdpOffer, mungedSdpOffer, sdpAnswer]
|
||||
private WebrtcDebugEventIssuer issuer;
|
||||
private WebrtcDebugEventOperation operation;
|
||||
private WebrtcDebugEventType type;
|
||||
private String content;
|
||||
private Long timestamp;
|
||||
|
||||
public WebrtcDebugEvent(Participant participant, String endpoint, String issuer, String operation, String type,
|
||||
String content) {
|
||||
public WebrtcDebugEvent(Participant participant, String endpoint, WebrtcDebugEventIssuer issuer,
|
||||
WebrtcDebugEventOperation operation, WebrtcDebugEventType type, String content) {
|
||||
this.participant = participant;
|
||||
this.endpoint = endpoint;
|
||||
this.issuer = issuer;
|
||||
|
@ -31,9 +43,9 @@ public class WebrtcDebugEvent {
|
|||
json.addProperty("user", participant.getFinalUserId());
|
||||
json.addProperty("connectionId", participant.getParticipantPublicId());
|
||||
json.addProperty("endpoint", this.endpoint);
|
||||
json.addProperty("issuer", this.issuer);
|
||||
json.addProperty("operation", this.operation);
|
||||
json.addProperty("type", this.type);
|
||||
json.addProperty("issuer", this.issuer.name());
|
||||
json.addProperty("operation", this.operation.name());
|
||||
json.addProperty("type", this.type.name());
|
||||
json.addProperty("content", this.content);
|
||||
json.addProperty("timestamp", this.timestamp);
|
||||
return json;
|
||||
|
|
|
@ -99,12 +99,6 @@ public class KurentoParticipant extends Participant {
|
|||
}
|
||||
|
||||
public void createPublishingEndpoint(MediaOptions mediaOptions, String streamId) {
|
||||
String type = mediaOptions.hasVideo() ? mediaOptions.getTypeOfVideo() : "MICRO";
|
||||
if (streamId == null) {
|
||||
streamId = IdentifierPrefixes.STREAM_ID + type.substring(0, Math.min(type.length(), 3)) + "_"
|
||||
+ RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(3)
|
||||
+ "_" + this.getParticipantPublicId();
|
||||
}
|
||||
publisher.setStreamId(streamId);
|
||||
publisher.setEndpointName(streamId);
|
||||
publisher.setMediaOptions(mediaOptions);
|
||||
|
@ -261,8 +255,7 @@ public class KurentoParticipant extends Participant {
|
|||
"Unable to create subscriber endpoint");
|
||||
}
|
||||
|
||||
String subscriberEndpointName = this.getParticipantPublicId() + "_"
|
||||
+ kSender.getPublisherStreamId();
|
||||
String subscriberEndpointName = calculateSubscriberEndpointName(kSender);
|
||||
|
||||
subscriber.setEndpointName(subscriberEndpointName);
|
||||
subscriber.getEndpoint().setName(subscriberEndpointName);
|
||||
|
@ -434,6 +427,17 @@ public class KurentoParticipant extends Participant {
|
|||
session.sendMediaError(this.getParticipantPrivateId(), desc);
|
||||
}
|
||||
|
||||
public String generateStreamId(MediaOptions mediaOptions) {
|
||||
String type = mediaOptions.hasVideo() ? mediaOptions.getTypeOfVideo() : "MICRO";
|
||||
return IdentifierPrefixes.STREAM_ID + type.substring(0, Math.min(type.length(), 3)) + "_"
|
||||
+ RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(3) + "_"
|
||||
+ this.getParticipantPublicId();
|
||||
}
|
||||
|
||||
public String calculateSubscriberEndpointName(Participant senderParticipant) {
|
||||
return this.getParticipantPublicId() + "_" + senderParticipant.getPublisherStreamId();
|
||||
}
|
||||
|
||||
private void releasePublisherEndpoint(EndReason reason, Long kmsDisconnectionTime) {
|
||||
if (publisher != null && publisher.getEndpoint() != null) {
|
||||
final ReadWriteLock closingLock = publisher.closingLock;
|
||||
|
|
|
@ -57,6 +57,11 @@ import io.openvidu.java.client.RecordingMode;
|
|||
import io.openvidu.java.client.RecordingProperties;
|
||||
import io.openvidu.java.client.SessionProperties;
|
||||
import io.openvidu.java.client.VideoCodec;
|
||||
import io.openvidu.server.cdr.CallDetailRecord;
|
||||
import io.openvidu.server.cdr.WebrtcDebugEvent;
|
||||
import io.openvidu.server.cdr.WebrtcDebugEvent.WebrtcDebugEventIssuer;
|
||||
import io.openvidu.server.cdr.WebrtcDebugEvent.WebrtcDebugEventOperation;
|
||||
import io.openvidu.server.cdr.WebrtcDebugEvent.WebrtcDebugEventType;
|
||||
import io.openvidu.server.core.EndReason;
|
||||
import io.openvidu.server.core.FinalUser;
|
||||
import io.openvidu.server.core.IdentifierPrefixes;
|
||||
|
@ -91,6 +96,9 @@ public class KurentoSessionManager extends SessionManager {
|
|||
@Autowired
|
||||
private SDPMunging sdpMunging;
|
||||
|
||||
@Autowired
|
||||
private CallDetailRecord CDR;
|
||||
|
||||
@Override
|
||||
/* Protected by Session.closingLock.readLock */
|
||||
public void joinRoom(Participant participant, String sessionId, Integer transactionId) {
|
||||
|
@ -361,6 +369,14 @@ public class KurentoSessionManager extends SessionManager {
|
|||
Set<Participant> participants = null;
|
||||
String sdpAnswer = null;
|
||||
|
||||
if (participant.isStreaming()) {
|
||||
log.warn("PARTICIPANT {}: Request to publish media in session {} but user is already publishing",
|
||||
participant.getParticipantPublicId(), participant.getSessionId());
|
||||
throw new OpenViduException(Code.USER_ALREADY_STREAMING_ERROR_CODE,
|
||||
"User " + participant.getParticipantPublicId() + " is already publishing in session "
|
||||
+ participant.getSessionId());
|
||||
}
|
||||
|
||||
KurentoMediaOptions kurentoOptions = (KurentoMediaOptions) mediaOptions;
|
||||
KurentoParticipant kParticipant = (KurentoParticipant) participant;
|
||||
KurentoSession kSession = kParticipant.getSession();
|
||||
|
@ -368,10 +384,17 @@ public class KurentoSessionManager extends SessionManager {
|
|||
boolean isTranscodingAllowed = kSession.getSessionProperties().isTranscodingAllowed();
|
||||
VideoCodec forcedVideoCodec = kSession.getSessionProperties().forcedVideoCodec();
|
||||
|
||||
final String streamId = kParticipant.generateStreamId(kurentoOptions);
|
||||
|
||||
CDR.log(new WebrtcDebugEvent(participant, streamId, WebrtcDebugEventIssuer.client,
|
||||
WebrtcDebugEventOperation.publish, WebrtcDebugEventType.sdpOffer, kurentoOptions.sdpOffer));
|
||||
|
||||
// Modify sdp if forced codec is defined
|
||||
if (forcedVideoCodec != VideoCodec.NONE && !participant.isIpcam()) {
|
||||
kurentoOptions.sdpOffer = sdpMunging.forceCodec(participant, kurentoOptions.sdpOffer,
|
||||
kurentoOptions.isOffer, kSession, true, false, isTranscodingAllowed, forcedVideoCodec);
|
||||
CDR.log(new WebrtcDebugEvent(participant, streamId, WebrtcDebugEventIssuer.client,
|
||||
WebrtcDebugEventOperation.publish, WebrtcDebugEventType.sdpOfferMunged, kurentoOptions.sdpOffer));
|
||||
}
|
||||
log.debug(
|
||||
"Request [PUBLISH_MEDIA] isOffer={} sdp={} "
|
||||
|
@ -379,7 +402,7 @@ public class KurentoSessionManager extends SessionManager {
|
|||
kurentoOptions.isOffer, kurentoOptions.sdpOffer, kurentoOptions.doLoopback, kurentoOptions.rtspUri,
|
||||
participant.getParticipantPublicId());
|
||||
|
||||
kParticipant.createPublishingEndpoint(mediaOptions, null);
|
||||
kParticipant.createPublishingEndpoint(mediaOptions, streamId);
|
||||
|
||||
/*
|
||||
* for (MediaElement elem : kurentoOptions.mediaElements) {
|
||||
|
@ -413,6 +436,9 @@ public class KurentoSessionManager extends SessionManager {
|
|||
kSession.getSessionId(), mediaOptions, sdpAnswer, participants, transactionId, e);
|
||||
}
|
||||
|
||||
CDR.log(new WebrtcDebugEvent(participant, streamId, WebrtcDebugEventIssuer.server,
|
||||
WebrtcDebugEventOperation.publish, WebrtcDebugEventType.sdpAnswer, sdpAnswer));
|
||||
|
||||
if (this.openviduConfig.isRecordingModuleEnabled()
|
||||
&& MediaMode.ROUTED.equals(kSession.getSessionProperties().mediaMode())
|
||||
&& kSession.getActivePublishers() == 0) {
|
||||
|
@ -518,6 +544,7 @@ public class KurentoSessionManager extends SessionManager {
|
|||
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());
|
||||
|
@ -525,14 +552,6 @@ public class KurentoSessionManager extends SessionManager {
|
|||
KurentoParticipant kParticipant = (KurentoParticipant) participant;
|
||||
session = ((KurentoParticipant) participant).getSession();
|
||||
Participant senderParticipant = session.getParticipantByPublicId(senderName);
|
||||
boolean isTranscodingAllowed = session.getSessionProperties().isTranscodingAllowed();
|
||||
VideoCodec forcedVideoCodec = session.getSessionProperties().forcedVideoCodec();
|
||||
|
||||
// Modify sdp if forced codec is defined
|
||||
if (forcedVideoCodec != VideoCodec.NONE && !participant.isIpcam()) {
|
||||
sdpOffer = sdpMunging.forceCodec(participant, sdpOffer, true, session, false, false,
|
||||
isTranscodingAllowed, forcedVideoCodec);
|
||||
}
|
||||
|
||||
if (senderParticipant == null) {
|
||||
log.warn(
|
||||
|
@ -551,12 +570,33 @@ public class KurentoSessionManager extends SessionManager {
|
|||
"User '" + senderName + " not streaming media in session '" + session.getSessionId() + "'");
|
||||
}
|
||||
|
||||
String subscriberEndpointName = kParticipant.calculateSubscriberEndpointName(senderParticipant);
|
||||
|
||||
CDR.log(new WebrtcDebugEvent(participant, subscriberEndpointName, WebrtcDebugEventIssuer.client,
|
||||
WebrtcDebugEventOperation.subscribe, WebrtcDebugEventType.sdpOffer, sdpOffer));
|
||||
|
||||
boolean isTranscodingAllowed = session.getSessionProperties().isTranscodingAllowed();
|
||||
VideoCodec forcedVideoCodec = session.getSessionProperties().forcedVideoCodec();
|
||||
|
||||
// Modify sdp if forced codec is defined
|
||||
if (forcedVideoCodec != VideoCodec.NONE && !participant.isIpcam()) {
|
||||
sdpOffer = sdpMunging.forceCodec(participant, sdpOffer, true, session, false, false,
|
||||
isTranscodingAllowed, forcedVideoCodec);
|
||||
|
||||
CDR.log(new WebrtcDebugEvent(participant, subscriberEndpointName, WebrtcDebugEventIssuer.client,
|
||||
WebrtcDebugEventOperation.subscribe, WebrtcDebugEventType.sdpOfferMunged, sdpOffer));
|
||||
}
|
||||
|
||||
sdpAnswer = kParticipant.receiveMediaFrom(senderParticipant, sdpOffer, false);
|
||||
if (sdpAnswer == null) {
|
||||
throw new OpenViduException(Code.MEDIA_SDP_ERROR_CODE,
|
||||
"Unable to generate SDP answer when subscribing '" + participant.getParticipantPublicId()
|
||||
+ "' to '" + senderName + "'");
|
||||
}
|
||||
|
||||
CDR.log(new WebrtcDebugEvent(participant, subscriberEndpointName, WebrtcDebugEventIssuer.server,
|
||||
WebrtcDebugEventOperation.subscribe, WebrtcDebugEventType.sdpAnswer, sdpAnswer));
|
||||
|
||||
} catch (OpenViduException e) {
|
||||
log.error("PARTICIPANT {}: Error subscribing to {}", participant.getParticipantPublicId(), senderName, e);
|
||||
sessionEventsHandler.onSubscribe(participant, session, null, transactionId, e);
|
||||
|
@ -1077,14 +1117,25 @@ public class KurentoSessionManager extends SessionManager {
|
|||
boolean isTranscodingAllowed = kSession.getSessionProperties().isTranscodingAllowed();
|
||||
VideoCodec forcedVideoCodec = kSession.getSessionProperties().forcedVideoCodec();
|
||||
|
||||
boolean sdpOfferHasBeenMunged = false;
|
||||
String originalSdpOffer = sdpOffer;
|
||||
|
||||
// Modify sdp if forced codec is defined
|
||||
if (forcedVideoCodec != VideoCodec.NONE && !participant.isIpcam()) {
|
||||
sdpOfferHasBeenMunged = true;
|
||||
sdpOffer = sdpMunging.forceCodec(participant, sdpOffer, true, kSession, isPublisher, true,
|
||||
isTranscodingAllowed, forcedVideoCodec);
|
||||
}
|
||||
|
||||
if (isPublisher) {
|
||||
|
||||
CDR.log(new WebrtcDebugEvent(participant, streamId, WebrtcDebugEventIssuer.client,
|
||||
WebrtcDebugEventOperation.reconnectPublisher, WebrtcDebugEventType.sdpOffer, originalSdpOffer));
|
||||
if (sdpOfferHasBeenMunged) {
|
||||
CDR.log(new WebrtcDebugEvent(participant, streamId, WebrtcDebugEventIssuer.client,
|
||||
WebrtcDebugEventOperation.reconnectPublisher, WebrtcDebugEventType.sdpOfferMunged, sdpOffer));
|
||||
}
|
||||
|
||||
// Reconnect publisher
|
||||
final KurentoMediaOptions kurentoOptions = (KurentoMediaOptions) kParticipant.getPublisher()
|
||||
.getMediaOptions();
|
||||
|
@ -1104,6 +1155,10 @@ public class KurentoSessionManager extends SessionManager {
|
|||
String sdpAnswer = kParticipant.publishToRoom(sdpType, sdpOffer, kurentoOptions.doLoopback, true);
|
||||
log.debug("SDP Answer for publishing reconnection PARTICIPANT {}: {}", participant.getParticipantPublicId(),
|
||||
sdpAnswer);
|
||||
|
||||
CDR.log(new WebrtcDebugEvent(participant, streamId, WebrtcDebugEventIssuer.server,
|
||||
WebrtcDebugEventOperation.reconnectPublisher, WebrtcDebugEventType.sdpAnswer, sdpAnswer));
|
||||
|
||||
sessionEventsHandler.onPublishMedia(participant, participant.getPublisherStreamId(),
|
||||
kParticipant.getPublisher().createdAt(), kSession.getSessionId(), kurentoOptions, sdpAnswer,
|
||||
new HashSet<Participant>(), transactionId, null);
|
||||
|
@ -1113,7 +1168,19 @@ public class KurentoSessionManager extends SessionManager {
|
|||
// Reconnect subscriber
|
||||
String senderPrivateId = kSession.getParticipantPrivateIdFromStreamId(streamId);
|
||||
if (senderPrivateId != null) {
|
||||
|
||||
KurentoParticipant sender = (KurentoParticipant) kSession.getParticipantByPrivateId(senderPrivateId);
|
||||
String subscriberEndpointName = kParticipant.calculateSubscriberEndpointName(sender);
|
||||
|
||||
CDR.log(new WebrtcDebugEvent(participant, subscriberEndpointName, WebrtcDebugEventIssuer.client,
|
||||
WebrtcDebugEventOperation.reconnectSubscriber, WebrtcDebugEventType.sdpOffer,
|
||||
originalSdpOffer));
|
||||
if (sdpOfferHasBeenMunged) {
|
||||
CDR.log(new WebrtcDebugEvent(participant, subscriberEndpointName, WebrtcDebugEventIssuer.client,
|
||||
WebrtcDebugEventOperation.reconnectSubscriber, WebrtcDebugEventType.sdpOfferMunged,
|
||||
sdpOffer));
|
||||
}
|
||||
|
||||
kParticipant.cancelReceivingMedia(sender, null, true);
|
||||
String sdpAnswer = kParticipant.receiveMediaFrom(sender, sdpOffer, true);
|
||||
if (sdpAnswer == null) {
|
||||
|
@ -1123,6 +1190,10 @@ public class KurentoSessionManager extends SessionManager {
|
|||
|
||||
log.debug("SDP Answer for subscribing reconnection PARTICIPANT {}: {}",
|
||||
participant.getParticipantPublicId(), sdpAnswer);
|
||||
|
||||
CDR.log(new WebrtcDebugEvent(participant, subscriberEndpointName, WebrtcDebugEventIssuer.server,
|
||||
WebrtcDebugEventOperation.reconnectSubscriber, WebrtcDebugEventType.sdpAnswer, sdpAnswer));
|
||||
|
||||
sessionEventsHandler.onSubscribe(participant, kSession, sdpAnswer, transactionId, null);
|
||||
} else {
|
||||
throw new OpenViduException(Code.USER_NOT_STREAMING_ERROR_CODE,
|
||||
|
|
|
@ -201,7 +201,11 @@ public class PublisherEndpoint extends MediaEndpoint {
|
|||
String sdpResponse = null;
|
||||
switch (sdpType) {
|
||||
case ANSWER:
|
||||
|
||||
/** THIS IS CURRENTLY NEVER CALLED **/
|
||||
sdpResponse = processAnswer(sdpString);
|
||||
/** THIS IS CURRENTLY NEVER CALLED **/
|
||||
|
||||
break;
|
||||
case OFFER:
|
||||
sdpResponse = processOffer(sdpString);
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.http.Header;
|
|||
import io.openvidu.server.cdr.CDREvent;
|
||||
import io.openvidu.server.cdr.CDREventName;
|
||||
import io.openvidu.server.cdr.CDRLogger;
|
||||
import io.openvidu.server.cdr.WebrtcDebugEvent;
|
||||
import io.openvidu.server.kurento.endpoint.KmsEvent;
|
||||
import io.openvidu.server.summary.SessionSummary;
|
||||
|
||||
|
@ -44,6 +45,10 @@ public class CDRLoggerWebhook implements CDRLogger {
|
|||
public void log(KmsEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(WebrtcDebugEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(SessionSummary sessionSummary) {
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ export class OpenviduRestService {
|
|||
|
||||
getAvailableParams(): Map<string, string[]> {
|
||||
const params = new Map<string, string[]>();
|
||||
this.sessionIdSession.forEach((sessionApi, sessionId, map) => {
|
||||
this.sessionIdSession.forEach((sessionApi, sessionId) => {
|
||||
params.set(sessionId, Array.from(this.sessionIdTokenOpenViduRole.get(sessionId).keys()));
|
||||
});
|
||||
return params;
|
||||
|
|
Loading…
Reference in New Issue