<commit_before>/*
 * Copyright @ 2018 - Present, 8x8 Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jitsi.nlj.transform.node.incoming

import org.jitsi.nlj.PacketInfo
import org.jitsi.nlj.rtcp.RtcpEventNotifier
import org.jitsi.nlj.stats.NodeStatsBlock
import org.jitsi.nlj.transform.node.TransformerNode
import org.jitsi.nlj.util.BufferPool
import org.jitsi.utils.logging2.cdebug
import org.jitsi.utils.logging2.cinfo
import org.jitsi.rtp.rtcp.CompoundRtcpPacket
import org.jitsi.rtp.rtcp.RtcpByePacket
import org.jitsi.rtp.rtcp.RtcpPacket
import org.jitsi.rtp.rtcp.RtcpRrPacket
import org.jitsi.rtp.rtcp.RtcpSdesPacket
import org.jitsi.rtp.rtcp.RtcpSrPacket
import org.jitsi.rtp.rtcp.RtcpXrPacket
import org.jitsi.rtp.rtcp.rtcpfb.payload_specific_fb.RtcpFbFirPacket
import org.jitsi.rtp.rtcp.rtcpfb.payload_specific_fb.RtcpFbPliPacket
import org.jitsi.rtp.rtcp.rtcpfb.payload_specific_fb.RtcpFbRembPacket
import org.jitsi.rtp.rtcp.rtcpfb.transport_layer_fb.RtcpFbNackPacket
import org.jitsi.rtp.rtcp.rtcpfb.transport_layer_fb.tcc.RtcpFbTccPacket
import org.jitsi.utils.logging2.Logger
import org.jitsi.utils.logging2.createChildLogger

class RtcpTermination(
    private val rtcpEventNotifier: RtcpEventNotifier,
    parentLogger: Logger
) : TransformerNode("RTCP termination") {
    private val logger = createChildLogger(parentLogger)
    private var packetReceiveCounts = mutableMapOf<String, Int>()
    /**
     * Number of packets we failed to forward because a compound packet contained more than one
     * packet we wanted to forward. Ideally this shouldn't happen.
     */
    private var numFailedToForward = 0

    override fun transform(packetInfo: PacketInfo): PacketInfo? {
        val compoundRtcp = packetInfo.packetAs<CompoundRtcpPacket>()
        var forwardedRtcp: RtcpPacket? = null

        compoundRtcp.packets.forEach { rtcpPacket ->
            when (rtcpPacket) {
                is RtcpFbPliPacket, is RtcpFbFirPacket, is RtcpSrPacket -> {
                    // We'll let these pass through and be forwarded to the conference (where they will be
                    // routed to the other endpoint(s))
                    // NOTE(brian): this should work fine as long as we can't receive 2 RTCP packets
                    // we want to forward in the same compound packet.  If we can, then we may need
                    // to turn this into a MultipleOutputNode
                    forwardedRtcp?.let {
                        logger.cinfo { "Failed to forward a packet of type ${it::class.simpleName} " +
                            ". Replaced by ${rtcpPacket::class.simpleName}." }
                        numFailedToForward++
                    }
                    forwardedRtcp = rtcpPacket
                }
                is RtcpSdesPacket, is RtcpRrPacket, is RtcpFbNackPacket,
                is RtcpByePacket, is RtcpFbTccPacket, is RtcpFbRembPacket -> {
                    // Supported, but no special handling here (any special handling will be in
                    // notifyRtcpReceived below
                }
                is RtcpXrPacket -> {
                    // Unsupported, but we get them when chrome does screenshare and the
                    // message below clouds up the logs.  They are still tracked as part
                    // of the packetReceiveCount
                }
                else -> {
                    logger.cinfo { "TODO: not yet handling RTCP packet of type ${rtcpPacket.packetType} ${rtcpPacket.javaClass}" }
                }
            }
            // TODO: keep an eye on if anything in here takes a while it could slow the packet pipeline down
            packetReceiveCounts.merge(rtcpPacket::class.simpleName!!, 1, Int::plus)
            rtcpEventNotifier.notifyRtcpReceived(rtcpPacket, packetInfo.receivedTime)

            (forwardedRtcp as? RtcpSrPacket)?.let {
                logger.cdebug { "Saw an sr from ssrc=${rtcpPacket.senderSsrc}, timestamp=${it.senderInfo.rtpTimestamp}" }
                forwardedRtcp = if (it.reportCount > 0) {
                    // Eliminates any report blocks as we don't want to relay those
                    it.cloneWithoutReportBlocks()
                } else {
                    it
                }
            }
        }

        return forwardedRtcp?.let {
            if (it.buffer != packetInfo.packet.buffer) {
                // We're not using the original packet's buffer, so we can return it to the pool
                BufferPool.returnBuffer(packetInfo.packet.buffer)<commit_msg>Log fmt field of unsupported RTCPFB packets. (#207)<commit_after>/*
 * Copyright @ 2018 - Present, 8x8 Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jitsi.nlj.transform.node.incoming

import org.jitsi.nlj.PacketInfo
import org.jitsi.nlj.rtcp.RtcpEventNotifier
import org.jitsi.nlj.stats.NodeStatsBlock
import org.jitsi.nlj.transform.node.TransformerNode
import org.jitsi.nlj.util.BufferPool
import org.jitsi.utils.logging2.cdebug
import org.jitsi.utils.logging2.cinfo
import org.jitsi.rtp.rtcp.CompoundRtcpPacket
import org.jitsi.rtp.rtcp.RtcpByePacket
import org.jitsi.rtp.rtcp.RtcpPacket
import org.jitsi.rtp.rtcp.RtcpRrPacket
import org.jitsi.rtp.rtcp.RtcpSdesPacket
import org.jitsi.rtp.rtcp.RtcpSrPacket
import org.jitsi.rtp.rtcp.RtcpXrPacket
import org.jitsi.rtp.rtcp.rtcpfb.UnsupportedRtcpFbPacket
import org.jitsi.rtp.rtcp.rtcpfb.payload_specific_fb.RtcpFbFirPacket
import org.jitsi.rtp.rtcp.rtcpfb.payload_specific_fb.RtcpFbPliPacket
import org.jitsi.rtp.rtcp.rtcpfb.payload_specific_fb.RtcpFbRembPacket
import org.jitsi.rtp.rtcp.rtcpfb.transport_layer_fb.RtcpFbNackPacket
import org.jitsi.rtp.rtcp.rtcpfb.transport_layer_fb.tcc.RtcpFbTccPacket
import org.jitsi.utils.logging2.Logger
import org.jitsi.utils.logging2.createChildLogger

class RtcpTermination(
    private val rtcpEventNotifier: RtcpEventNotifier,
    parentLogger: Logger
) : TransformerNode("RTCP termination") {
    private val logger = createChildLogger(parentLogger)
    private var packetReceiveCounts = mutableMapOf<String, Int>()
    /**
     * Number of packets we failed to forward because a compound packet contained more than one
     * packet we wanted to forward. Ideally this shouldn't happen.
     */
    private var numFailedToForward = 0

    override fun transform(packetInfo: PacketInfo): PacketInfo? {
        val compoundRtcp = packetInfo.packetAs<CompoundRtcpPacket>()
        var forwardedRtcp: RtcpPacket? = null

        compoundRtcp.packets.forEach { rtcpPacket ->
            when (rtcpPacket) {
                is RtcpFbPliPacket, is RtcpFbFirPacket, is RtcpSrPacket -> {
                    // We'll let these pass through and be forwarded to the conference (where they will be
                    // routed to the other endpoint(s))
                    // NOTE(brian): this should work fine as long as we can't receive 2 RTCP packets
                    // we want to forward in the same compound packet.  If we can, then we may need
                    // to turn this into a MultipleOutputNode
                    forwardedRtcp?.let {
                        logger.cinfo { "Failed to forward a packet of type ${it::class.simpleName} " +
                            ". Replaced by ${rtcpPacket::class.simpleName}." }
                        numFailedToForward++
                    }
                    forwardedRtcp = rtcpPacket
                }
                is RtcpSdesPacket, is RtcpRrPacket, is RtcpFbNackPacket,
                is RtcpByePacket, is RtcpFbTccPacket, is RtcpFbRembPacket -> {
                    // Supported, but no special handling here (any special handling will be in
                    // notifyRtcpReceived below
                }
                is RtcpXrPacket -> {
                    // Unsupported, but we get them when chrome does screenshare and the
                    // message below clouds up the logs.  They are still tracked as part
                    // of the packetReceiveCount
                }
                is UnsupportedRtcpFbPacket -> {
                    logger.cinfo { "TODO: not yet handling RTCP packet of type ${rtcpPacket.packetType} fmt ${rtcpPacket.reportCount} ${rtcpPacket.javaClass}" }
                }
                else -> {
                    logger.cinfo { "TODO: not yet handling RTCP packet of type ${rtcpPacket.packetType} ${rtcpPacket.javaClass}" }
                }
            }
            // TODO: keep an eye on if anything in here takes a while it could slow the packet pipeline down
            packetReceiveCounts.merge(rtcpPacket::class.simpleName!!, 1, Int::plus)
            rtcpEventNotifier.notifyRtcpReceived(rtcpPacket, packetInfo.receivedTime)

            (forwardedRtcp as? RtcpSrPacket)?.let {
                logger.cdebug { "Saw an sr from ssrc=${rtcpPacket.senderSsrc}, timestamp=${it.senderInfo.rtpTimestamp}" }
                forwardedRtcp = if (it.reportCount > 0) {
                    // Eliminates any report blocks as we don't want to relay those
                    it.cloneWithoutReportBlocks()
                } else {
                    it
                }
            }
        }

        return forwardedRtcp?.let {
            if (it.buffer != packetInfo.packet.buffer) {
                // We're not using the original packet's buffer, so we can return it to the pool
                BufferPool.returnBuffer(packetInfo.packet.buffer)
{'fraction_non_alphanumeric': 0.07638623326959847, 'fraction_numerical': 0.00372848948374761, 'mean_word_length': 2.313588850174216, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '420305', 'n_tokens_mistral': 3083, 'n_tokens_neox': 2924, 'n_words': 839}