// RFC3550 6.4.2 RR: Receiver Report RTCP Packet

#include "rtp-internal.h"
#include "rtp-util.h"

void rtcp_rr_unpack(struct rtp_context *ctx, const rtcp_header_t *header, const uint8_t* ptr, size_t bytes)
{
	uint32_t i;
	rtcp_rb_t *rb;
	struct rtcp_msg_t msg;
	struct rtp_member *receiver;

	assert(24 == sizeof(rtcp_rb_t) && 4 == sizeof(rtcp_rr_t));
	if (bytes < 4/*sizeof(rtcp_rr_t)*/ + header->rc * 24/*sizeof(rtcp_rb_t)*/) // RR SSRC + Report Block
	{
		assert(0);
		return;
	}
	msg.ssrc = nbo_r32(ptr);
	msg.type = RTCP_RR;

	receiver = rtp_member_fetch(ctx, msg.ssrc);
	if(!receiver) return; // error

	assert(receiver != ctx->self);
	assert(receiver->rtcp_sr.ssrc == msg.ssrc);
	//assert(receiver->rtcp_rb.ssrc == msg.ssrc);
	receiver->rtcp_clock = rtpclock(); // last received clock, for keep-alive

	ptr += 4;
	// report block
	for(i = 0; i < header->rc; i++, ptr+=24/*sizeof(rtcp_rb_t)*/) 
	{
		msg.u.rr.ssrc = nbo_r32(ptr);
		//if(msg.u.rr.ssrcssrc != ctx->self->ssrc)
		//	continue; // ignore
		//rb = &receiver->rtcp_rb;

		rb = &msg.u.rr;
		rb->fraction = ptr[4];
		rb->cumulative = (((uint32_t)ptr[5])<<16) | (((uint32_t)ptr[6])<<8)| ptr[7];
		rb->exthsn = nbo_r32(ptr+8);
		rb->jitter = nbo_r32(ptr+12);
		rb->lsr = nbo_r32(ptr+16);
		rb->dlsr = nbo_r32(ptr+20);

		ctx->handler.on_rtcp(ctx->cbparam, &msg);
	}
}

int rtcp_rr_pack(struct rtp_context *ctx, uint8_t* ptr, int bytes)
{
	// RFC3550 6.1 RTCP Packet Format
	// An individual RTP participant should send only one compound RTCP packet per report interval
	// in order for the RTCP bandwidth per participant to be estimated correctly (see Section 6.2), 
	// except when the compound RTCP packet is split for partial encryption as described in Section 9.1.
	uint32_t i;
	rtcp_header_t header;

	assert(4 == sizeof(rtcp_rr_t));
	assert(24 == sizeof(rtcp_rb_t));
	assert(rtp_member_list_count(ctx->senders) < 32);
	header.v = 2;
	header.p = 0;
	header.pt = RTCP_RR;
	header.rc = MIN(31, rtp_member_list_count(ctx->senders));
	header.length = (4/*sizeof(rtcp_rr_t)*/ + header.rc*24/*sizeof(rtcp_rb_t)*/) / 4;

	if((uint32_t)bytes < 4 + header.length * 4)
		return 4 + header.length * 4;

	nbo_write_rtcp_header(ptr, &header);

	// receiver SSRC
	nbo_w32(ptr+4, ctx->self->ssrc);

	ptr += 8;
	// report block
	for(i = 0; i < header.rc; i++)
	{
		struct rtp_member *sender;

		sender = rtp_member_list_get(ctx->senders, i);
		if(0 == sender->rtp_packets || sender->ssrc == ctx->self->ssrc)
			continue; // don't receive any packet

		ptr += rtcp_report_block(sender, ptr, 24);
	}

	return (header.length+1) * 4;
}
