From eab721e557520bf47c2362c6618831ec499bb33d Mon Sep 17 00:00:00 2001 From: bgrozev Date: Thu, 16 Mar 2023 10:37:48 -0400 Subject: [PATCH] feat: Read initial-last-n from jingle, set it in colibri2. (#1052) * feat: Read initial-last-n from jingle, set it in colibri2. * chore: Update jitsi-xmpp-extensions. --- .../jicofo/bridge/colibri/Colibri2Session.kt | 10 ++++++-- .../bridge/colibri/ColibriSessionManager.kt | 10 +++----- .../bridge/colibri/ColibriV2SessionManager.kt | 4 +++- .../conference/JitsiMeetConferenceImpl.java | 24 +++++++++++++++---- .../jitsi/jicofo/conference/Participant.kt | 17 ++++++++++++- pom.xml | 2 +- 6 files changed, 51 insertions(+), 16 deletions(-) diff --git a/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/Colibri2Session.kt b/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/Colibri2Session.kt index 0a388167b8..62c789f195 100644 --- a/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/Colibri2Session.kt +++ b/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/Colibri2Session.kt @@ -34,6 +34,7 @@ import org.jitsi.xmpp.extensions.colibri2.Colibri2Relay import org.jitsi.xmpp.extensions.colibri2.ConferenceModifiedIQ import org.jitsi.xmpp.extensions.colibri2.ConferenceModifyIQ import org.jitsi.xmpp.extensions.colibri2.Endpoints +import org.jitsi.xmpp.extensions.colibri2.InitialLastN import org.jitsi.xmpp.extensions.colibri2.Media import org.jitsi.xmpp.extensions.colibri2.Sctp import org.jitsi.xmpp.extensions.colibri2.Transport @@ -117,9 +118,10 @@ class Colibri2Session( /** The transport info to set for the colibri2 endpoint, or null if it is not to be modified. */ transport: IceUdpTransportPacketExtension?, /** The sources to set for the colibri2 endpoint, or null if the sources are not to be modified. */ - sources: EndpointSourceSet? + sources: EndpointSourceSet?, + initialLastN: InitialLastN? ) { - if (transport == null && sources == null) { + if (transport == null && sources == null && initialLastN == null) { logger.info("Nothing to update.") return } @@ -138,6 +140,10 @@ class Colibri2Session( endpoint.setSources(sources.toColibriMediaSources(participant.id)) } + initialLastN?.let { + endpoint.setInitialLastN(it) + } + request.addEndpoint(endpoint.build()) sendRequest(request.build(), "updateParticipant") } diff --git a/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/ColibriSessionManager.kt b/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/ColibriSessionManager.kt index 92f2b122e4..1f8c95d5ff 100644 --- a/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/ColibriSessionManager.kt +++ b/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/ColibriSessionManager.kt @@ -21,6 +21,7 @@ import org.jitsi.jicofo.bridge.Bridge import org.jitsi.jicofo.conference.source.EndpointSourceSet import org.jitsi.utils.MediaType import org.jitsi.utils.OrderedJsonObject +import org.jitsi.xmpp.extensions.colibri2.InitialLastN import org.jitsi.xmpp.extensions.colibri2.Media import org.jitsi.xmpp.extensions.jingle.IceUdpTransportPacketExtension @@ -42,19 +43,14 @@ interface ColibriSessionManager { @Throws(ColibriAllocationFailedException::class, BridgeSelectionFailedException::class) fun allocate(participant: ParticipantAllocationParameters): ColibriAllocation - /** For use in java because @JvmOverloads is not available for interfaces. */ - fun updateParticipant( - participantId: String, - transport: IceUdpTransportPacketExtension? = null, - sources: EndpointSourceSet? = null, - ) = updateParticipant(participantId, transport, sources, false) - fun updateParticipant( participantId: String, transport: IceUdpTransportPacketExtension? = null, sources: EndpointSourceSet? = null, + initialLastN: InitialLastN? = null, suppressLocalBridgeUpdate: Boolean = false ) + fun getBridgeSessionId(participantId: String): String? /** diff --git a/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/ColibriV2SessionManager.kt b/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/ColibriV2SessionManager.kt index eaf3b5f64a..96bb513c8b 100644 --- a/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/ColibriV2SessionManager.kt +++ b/jicofo-selector/src/main/kotlin/org/jitsi/jicofo/bridge/colibri/ColibriV2SessionManager.kt @@ -40,6 +40,7 @@ import org.jitsi.utils.logging2.Logger import org.jitsi.utils.logging2.createChildLogger import org.jitsi.xmpp.extensions.colibri2.Colibri2Error import org.jitsi.xmpp.extensions.colibri2.ConferenceModifiedIQ +import org.jitsi.xmpp.extensions.colibri2.InitialLastN import org.jitsi.xmpp.extensions.jingle.IceUdpTransportPacketExtension import org.jivesoftware.smack.AbstractXMPPConnection import org.jivesoftware.smack.StanzaCollector @@ -518,6 +519,7 @@ class ColibriV2SessionManager( participantId: String, transport: IceUdpTransportPacketExtension?, sources: EndpointSourceSet?, + initialLastN: InitialLastN?, suppressLocalBridgeUpdate: Boolean ) = synchronized(syncRoot) { logger.info("Updating $participantId with transport=$transport, sources=$sources") @@ -530,7 +532,7 @@ class ColibriV2SessionManager( return } if (!suppressLocalBridgeUpdate) { - participantInfo.session.updateParticipant(participantInfo, transport, sources) + participantInfo.session.updateParticipant(participantInfo, transport, sources, initialLastN) } if (sources != null) { participantInfo.sources = sources diff --git a/jicofo/src/main/java/org/jitsi/jicofo/conference/JitsiMeetConferenceImpl.java b/jicofo/src/main/java/org/jitsi/jicofo/conference/JitsiMeetConferenceImpl.java index 582f786a1c..a6327d5c95 100644 --- a/jicofo/src/main/java/org/jitsi/jicofo/conference/JitsiMeetConferenceImpl.java +++ b/jicofo/src/main/java/org/jitsi/jicofo/conference/JitsiMeetConferenceImpl.java @@ -33,6 +33,7 @@ import org.jitsi.utils.*; import org.jitsi.utils.logging2.*; import org.jitsi.utils.logging2.Logger; +import org.jitsi.xmpp.extensions.colibri2.*; import org.jitsi.xmpp.extensions.jibri.*; import org.jitsi.xmpp.extensions.jingle.*; @@ -1047,7 +1048,9 @@ public void updateTransport(@NotNull Participant participant, @NotNull IceUdpTra getColibriSessionManager().updateParticipant( participant.getEndpointId(), transport, - null /* no change in sources, just transport */); + null /* no change in sources, just transport */, + null, + false); } /** @@ -1092,7 +1095,12 @@ public void addSource( // Updates source groups on the bridge // We may miss the notification, but the state will be synced up after conference has been relocated to the new // bridge - getColibriSessionManager().updateParticipant(participant.getEndpointId(), null, participant.getSources()); + getColibriSessionManager().updateParticipant( + participant.getEndpointId(), + null, + participant.getSources(), + null, + false); propagateNewSources(participant, sourcesAccepted); } @@ -1126,6 +1134,7 @@ public void removeSources( participant.getEndpointId(), null, participant.getSources(), + null, false); sendSourceRemove(new ConferenceSourceMap(participantId, sourcesAcceptedToBeRemoved), participant); @@ -1137,7 +1146,8 @@ public void removeSources( void acceptSession( @NotNull Participant participant, @NotNull EndpointSourceSet sourcesAdvertised, - IceUdpTransportPacketExtension transport) + IceUdpTransportPacketExtension transport, + @Nullable InitialLastN initialLastN) throws ValidationFailedException { String participantId = participant.getEndpointId(); @@ -1148,7 +1158,12 @@ void acceptSession( sourcesAccepted = conferenceSources.tryToAdd(participantId, sourcesAdvertised); } - getColibriSessionManager().updateParticipant(participantId, transport, getSourcesForParticipant(participant)); + getColibriSessionManager().updateParticipant( + participantId, + transport, + getSourcesForParticipant(participant), + initialLastN, + false); if (!sourcesAccepted.isEmpty()) { @@ -1182,6 +1197,7 @@ private void removeParticipantSources(@NotNull Participant participant, boolean participant.getEndpointId(), null, participant.getSources(), + null, true); if (sendSourceRemove) diff --git a/jicofo/src/main/kotlin/org/jitsi/jicofo/conference/Participant.kt b/jicofo/src/main/kotlin/org/jitsi/jicofo/conference/Participant.kt index c2f2f1d73e..0082081879 100644 --- a/jicofo/src/main/kotlin/org/jitsi/jicofo/conference/Participant.kt +++ b/jicofo/src/main/kotlin/org/jitsi/jicofo/conference/Participant.kt @@ -39,6 +39,7 @@ import org.jitsi.jicofo.xmpp.muc.hasModeratorRights import org.jitsi.utils.OrderedJsonObject import org.jitsi.utils.logging2.Logger import org.jitsi.utils.logging2.LoggerImpl +import org.jitsi.xmpp.extensions.colibri2.InitialLastN import org.jitsi.xmpp.extensions.jingle.ContentPacketExtension import org.jitsi.xmpp.extensions.jingle.JingleAction import org.jitsi.xmpp.extensions.jingle.JingleIQ @@ -205,27 +206,38 @@ open class Participant @JvmOverloads constructor( /** Return `true` if this participant supports source name signaling. */ fun hasSourceNameSupport() = supportedFeatures.contains(Features.SOURCE_NAMES) + /** Return `true` if this participant supports SSRC rewriting functionality. */ fun hasSsrcRewritingSupport() = supportedFeatures.contains(Features.SSRC_REWRITING_V1) + /** Return `true` if SSRC rewriting should be used for this participant. */ fun useSsrcRewriting() = ConferenceConfig.config.useSsrcRewriting && hasSsrcRewritingSupport() + /** Return `true` if this participant supports receiving Jingle sources encoded in JSON. */ fun supportsJsonEncodedSources() = supportedFeatures.contains(Features.JSON_SOURCES) fun supportsReceivingMultipleVideoStreams() = supportedFeatures.contains(Features.RECEIVE_MULTIPLE_STREAMS) + /** Returns `true` iff this participant supports REMB. */ fun hasRembSupport() = supportedFeatures.contains(Features.REMB) + /** Returns `true` iff this participant supports TCC. */ fun hasTccSupport() = supportedFeatures.contains(Features.TCC) + /** Returns `true` iff this participant supports RTX. */ fun hasRtxSupport() = supportedFeatures.contains(Features.RTX) + /** Returns `true` iff this participant supports RED for opus. */ fun hasOpusRedSupport() = supportedFeatures.contains(Features.OPUS_RED) + /** Returns true if RTP audio is supported by this peer. */ fun hasAudioSupport() = supportedFeatures.contains(Features.AUDIO) + /** Returns true if RTP video is supported by this peer. */ fun hasVideoSupport() = supportedFeatures.contains(Features.VIDEO) + /** Returns true if RTP audio can be muted for this peer. */ fun hasAudioMuteSupport() = supportedFeatures.contains(Features.AUDIO_MUTE) + /** Returns true if this peer supports DTLS/SCTP. */ fun hasSctpSupport() = supportedFeatures.contains(Features.SCTP) @@ -339,6 +351,7 @@ open class Participant @JvmOverloads constructor( * support unmuting). */ fun shouldSuppressForceMute() = (chatMember.isJigasi && !hasAudioMuteSupport()) || chatMember.isJibri + /** Checks whether this [Participant]'s role has moderator rights. */ fun hasModeratorRights() = chatMember.role.hasModeratorRights() override fun toString() = "Participant[$mucJid]" @@ -447,9 +460,11 @@ open class Participant @JvmOverloads constructor( if (!sourcesAdvertised.isEmpty() && this@Participant.chatMember.role == MemberRole.VISITOR) { return StanzaError.from(StanzaError.Condition.forbidden, "sources not allowed for visitors").build() } + val initialLastN: InitialLastN? = + contents.find { it.name == "video" }?.getChildExtension(InitialLastN::class.java) try { - conference.acceptSession(this@Participant, sourcesAdvertised, contents.getTransport()) + conference.acceptSession(this@Participant, sourcesAdvertised, contents.getTransport(), initialLastN) } catch (e: ValidationFailedException) { return StanzaError.from(StanzaError.Condition.bad_request, e.message).build() } diff --git a/pom.xml b/pom.xml index edc15d5397..ef1f320405 100644 --- a/pom.xml +++ b/pom.xml @@ -176,7 +176,7 @@ ${project.groupId} jitsi-xmpp-extensions - 1.0-64-gf221325 + 1.0-71-g8c6cdeb org.slf4j