1 /*
2  * The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) implementation with additional features.
3  * Copyright (C) 2017 Belledonne Communications SARL
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19 
20 /***************************************************************************
21  *            rtcp.c
22  *
23  *  Wed Dec  1 11:45:30 2004
24  *  Copyright  2004  Simon Morlat
25  *  Email simon dot morlat at linphone dot org
26  ****************************************************************************/
27 
28 #include "ortp/ortp.h"
29 #include "ortp/rtpsession.h"
30 #include "ortp/rtcp.h"
31 #include "utils.h"
32 #include "rtpsession_priv.h"
33 #include "jitterctl.h"
34 
35 #define rtcp_bye_set_ssrc(b,pos,ssrc)	(b)->ssrc[pos]=htonl(ssrc)
36 #define rtcp_bye_get_ssrc(b,pos)		ntohl((b)->ssrc[pos])
37 
38 
rtcp_create_simple_bye_packet(uint32_t ssrc,const char * reason)39 static mblk_t *rtcp_create_simple_bye_packet(uint32_t ssrc, const char *reason) {
40 	int packet_size;
41 	int strsize = 0;
42 	int strpadding = 0;
43 	mblk_t *mp;
44 	rtcp_bye_t *rtcp;
45 
46 	packet_size = RTCP_BYE_HEADER_SIZE;
47 	if (reason!=NULL) {
48 		strsize=(int)MIN(strlen(reason),RTCP_BYE_REASON_MAX_STRING_SIZE);
49 		if (strsize > 0) {
50 			strpadding = 3 - (strsize % 4);
51 			packet_size += 1 + strsize + strpadding;
52 		}
53 	}
54 	mp	= allocb(packet_size, 0);
55 
56 	rtcp = (rtcp_bye_t*)mp->b_rptr;
57 	rtcp_common_header_init(&rtcp->ch,NULL,RTCP_BYE,1,packet_size);
58 	rtcp->ssrc[0] = htonl(ssrc);
59 	mp->b_wptr += RTCP_BYE_HEADER_SIZE;
60 	/* append the reason if any*/
61 	if (reason!=NULL) {
62 		const char pad[] = {0, 0, 0};
63 		unsigned char strsize_octet = (unsigned char)strsize;
64 
65 		appendb(mp, (const char*)&strsize_octet, 1, FALSE);
66 		appendb(mp, reason,strsize, FALSE);
67 		appendb(mp, pad,strpadding, FALSE);
68 	}
69 	return mp;
70 }
71 
sdes_chunk_new(uint32_t ssrc)72 static mblk_t *sdes_chunk_new(uint32_t ssrc){
73 	mblk_t *m=allocb(RTCP_SDES_CHUNK_DEFAULT_SIZE,0);
74 	sdes_chunk_t *sc=(sdes_chunk_t*)m->b_rptr;
75 	sc->csrc=htonl(ssrc);
76 	m->b_wptr+=sizeof(sc->csrc);
77 	return m;
78 }
79 
sdes_chunk_append_item(mblk_t * m,rtcp_sdes_type_t sdes_type,const char * content)80 static mblk_t * sdes_chunk_append_item(mblk_t *m, rtcp_sdes_type_t sdes_type, const char *content) {
81 	if ( content )
82 	{
83 		sdes_item_t si;
84 		si.item_type=sdes_type;
85 		si.len=(uint8_t) MIN(strlen(content),RTCP_SDES_MAX_STRING_SIZE);
86 		m=appendb(m,(char*)&si,RTCP_SDES_ITEM_HEADER_SIZE,FALSE);
87 		m=appendb(m,content,si.len,FALSE);
88 	}
89 	return m;
90 }
91 
sdes_chunk_set_ssrc(mblk_t * m,uint32_t ssrc)92 static void sdes_chunk_set_ssrc(mblk_t *m, uint32_t ssrc){
93 	sdes_chunk_t *sc=(sdes_chunk_t*)m->b_rptr;
94 	sc->csrc=htonl(ssrc);
95 }
96 
97 #define sdes_chunk_get_ssrc(m) ntohl(((sdes_chunk_t*)((m)->b_rptr))->csrc)
98 
sdes_chunk_pad(mblk_t * m)99 static mblk_t * sdes_chunk_pad(mblk_t *m){
100 	return appendb(m,"",1,TRUE);
101 }
102 
sdes_chunk_set_minimal_items(mblk_t * m,const char * cname)103 static mblk_t * sdes_chunk_set_minimal_items(mblk_t *m, const char *cname) {
104 	if (cname == NULL) {
105 		cname = "Unknown";
106 	}
107 	return sdes_chunk_append_item(m, RTCP_SDES_CNAME, cname);
108 }
109 
sdes_chunk_set_full_items(mblk_t * m,const char * cname,const char * name,const char * email,const char * phone,const char * loc,const char * tool,const char * note)110 static mblk_t * sdes_chunk_set_full_items(mblk_t *m, const char *cname,
111 	const char *name, const char *email, const char *phone, const char *loc,
112 	const char *tool, const char *note) {
113 	m = sdes_chunk_set_minimal_items(m, cname);
114 	m = sdes_chunk_append_item(m, RTCP_SDES_NAME, name);
115 	m = sdes_chunk_append_item(m, RTCP_SDES_EMAIL, email);
116 	m = sdes_chunk_append_item(m, RTCP_SDES_PHONE, phone);
117 	m = sdes_chunk_append_item(m, RTCP_SDES_LOC, loc);
118 	m = sdes_chunk_append_item(m, RTCP_SDES_TOOL, tool);
119 	m = sdes_chunk_append_item(m, RTCP_SDES_NOTE, note);
120 	m = sdes_chunk_pad(m);
121 	return m;
122 }
123 
124 /**
125  * Set session's SDES item for automatic sending of RTCP compound packets.
126  * If some items are not specified, use NULL.
127 **/
rtp_session_set_source_description(RtpSession * session,const char * cname,const char * name,const char * email,const char * phone,const char * loc,const char * tool,const char * note)128 void rtp_session_set_source_description(RtpSession *session, const char *cname,
129 	const char *name, const char *email, const char *phone, const char *loc,
130 	const char *tool, const char *note) {
131 	mblk_t *m;
132 	mblk_t *chunk = sdes_chunk_new(session->snd.ssrc);
133 	if (strlen(cname)>255) {
134 		/*
135 		 * rfc3550,
136 		 * 6.5 SDES: Source Description RTCP Packet
137 		 * ...
138 		 * Note that the text can be no longer than 255 octets,
139 		 *
140 		 * */
141 		ortp_warning("Cname [%s] too long for session [%p]",cname,session);
142 	}
143 
144 	sdes_chunk_set_full_items(chunk, cname, name, email, phone, loc, tool, note);
145 	if (session->full_sdes != NULL)
146 		freemsg(session->full_sdes);
147 	session->full_sdes = chunk;
148 	chunk = sdes_chunk_new(session->snd.ssrc);
149 	m = sdes_chunk_set_minimal_items(chunk, cname);
150 	m = sdes_chunk_pad(m);
151 	if (session->minimal_sdes != NULL)
152 		freemsg(session->minimal_sdes);
153 	session->minimal_sdes = chunk;
154 }
155 
rtp_session_add_contributing_source(RtpSession * session,uint32_t csrc,const char * cname,const char * name,const char * email,const char * phone,const char * loc,const char * tool,const char * note)156 void rtp_session_add_contributing_source(RtpSession *session, uint32_t csrc,
157 	const char *cname, const char *name, const char *email, const char *phone,
158 	const char *loc, const char *tool, const char *note) {
159 	mblk_t *chunk = sdes_chunk_new(csrc);
160 	sdes_chunk_set_full_items(chunk, cname, name, email, phone, loc, tool, note);
161 	putq(&session->contributing_sources, chunk);
162 }
163 
rtp_session_remove_contributing_source(RtpSession * session,uint32_t ssrc)164 void rtp_session_remove_contributing_source(RtpSession *session, uint32_t ssrc) {
165 	queue_t *q=&session->contributing_sources;
166 	mblk_t *tmp;
167 	for (tmp=qbegin(q); !qend(q,tmp); tmp=qnext(q,tmp)){
168 		uint32_t csrc=sdes_chunk_get_ssrc(tmp);
169 		if (csrc==ssrc) {
170 			remq(q,tmp);
171 			break;
172 		}
173 	}
174 	tmp=rtcp_create_simple_bye_packet(ssrc, NULL);
175 	rtp_session_rtcp_send(session,tmp);
176 }
177 
rtcp_common_header_init(rtcp_common_header_t * ch,RtpSession * s,int type,int rc,size_t bytes_len)178 void rtcp_common_header_init(rtcp_common_header_t *ch, RtpSession *s,int type, int rc, size_t bytes_len){
179 	rtcp_common_header_set_version(ch,2);
180 	rtcp_common_header_set_padbit(ch,0);
181 	rtcp_common_header_set_packet_type(ch,type);
182 	rtcp_common_header_set_rc(ch,rc);	/* as we don't yet support multi source receiving */
183 	rtcp_common_header_set_length(ch,(unsigned short)((bytes_len/4)-1));
184 }
185 
rtp_session_create_rtcp_sdes_packet(RtpSession * session,bool_t full)186 mblk_t* rtp_session_create_rtcp_sdes_packet(RtpSession *session, bool_t full) {
187 	mblk_t *mp = allocb(sizeof(rtcp_common_header_t), 0);
188 	rtcp_common_header_t *rtcp;
189 	mblk_t *tmp;
190 	mblk_t *m = mp;
191 	mblk_t *sdes;
192 	queue_t *q;
193 	int rc = 0;
194 
195 	sdes = (full == TRUE) ? session->full_sdes : session->minimal_sdes;
196 	rtcp = (rtcp_common_header_t *)mp->b_wptr;
197 	mp->b_wptr += sizeof(rtcp_common_header_t);
198 
199 	/* Concatenate all sdes chunks. */
200 	sdes_chunk_set_ssrc(sdes, session->snd.ssrc);
201 	m = concatb(m, dupmsg(sdes));
202 	rc++;
203 
204 	if (full == TRUE) {
205 		q = &session->contributing_sources;
206 		for (tmp = qbegin(q); !qend(q, tmp); tmp = qnext(q, mp)) {
207 			m = concatb(m, dupmsg(tmp));
208 			rc++;
209 		}
210 	}
211 	rtcp_common_header_init(rtcp, session, RTCP_SDES, rc, msgdsize(mp));
212 
213 	return mp;
214 }
215 
sender_info_init(sender_info_t * info,RtpSession * session)216 static void sender_info_init(sender_info_t *info, RtpSession *session){
217 	struct timeval tv;
218 	uint64_t ntp;
219 	ortp_gettimeofday(&tv,NULL);
220 	ntp=ortp_timeval_to_ntp(&tv);
221 	info->ntp_timestamp_msw=htonl(ntp >>32);
222 	info->ntp_timestamp_lsw=htonl(ntp & 0xFFFFFFFF);
223 	info->rtp_timestamp=htonl(session->rtp.snd_last_ts);
224 	info->senders_packet_count=(uint32_t) htonl((u_long) session->stats.packet_sent);
225 	info->senders_octet_count=(uint32_t) htonl((u_long) session->rtp.sent_payload_bytes);
226 	session->rtp.last_rtcp_packet_count=(uint32_t)session->stats.packet_sent;
227 }
228 
report_block_init(report_block_t * b,RtpSession * session)229 static void report_block_init(report_block_t *b, RtpSession *session){
230 	int packet_loss=0;
231 	int loss_fraction=0;
232 	RtpStream *stream=&session->rtp;
233 	uint32_t delay_snc_last_sr=0;
234 
235 	/* compute the statistics */
236 	if (stream->hwrcv_since_last_SR!=0){
237 		uint32_t expected_packets=(uint32_t)(stream->hwrcv_extseq - stream->hwrcv_seq_at_last_SR);
238 
239 		if ( session->flags & RTCP_OVERRIDE_LOST_PACKETS ) {
240 			/* If the test mode is enabled, replace the lost packet field with
241 			the test vector value set by rtp_session_rtcp_set_lost_packet_value() */
242 			packet_loss = session->lost_packets_test_vector;
243 			/* The test value is the definite cumulative one, no need to increment
244 			it each time a packet is sent */
245 			session->stats.cum_packet_loss = packet_loss;
246 		}else {
247 			/* Normal mode */
248 			packet_loss = (int)(expected_packets - stream->hwrcv_since_last_SR);
249 			session->stats.cum_packet_loss += packet_loss;
250 		}
251 		if (expected_packets>0){/*prevent division by zero and negative loss fraction*/
252 			loss_fraction=(int)( 256 * packet_loss) / expected_packets;
253 			/*make sure this fits into 8 bit unsigned*/
254 			if (loss_fraction>255) loss_fraction=255;
255 			else if (loss_fraction<0) loss_fraction=0;
256 		}else{
257 			loss_fraction=0;
258 		}
259 	}
260 	ortp_debug("report_block_init[%p]:\n"
261 		"\texpected_packets=%d=%u-%u\n"
262 		"\thwrcv_since_last_SR=%u\n"
263 		"\tpacket_loss=%d\n"
264 		"\tcum_packet_loss=%lld\n"
265 		"\tloss_fraction=%f%%\n"
266 		, session
267 		, stream->hwrcv_extseq - stream->hwrcv_seq_at_last_SR, stream->hwrcv_extseq, stream->hwrcv_seq_at_last_SR
268 		, stream->hwrcv_since_last_SR
269 		, packet_loss
270 		, (long long)session->stats.cum_packet_loss
271 		, loss_fraction/2.56
272 	);
273 
274 	/* reset them */
275 	stream->hwrcv_since_last_SR=0;
276 	stream->hwrcv_seq_at_last_SR=stream->hwrcv_extseq;
277 
278 	if (stream->last_rcv_SR_time.tv_sec!=0){
279 		struct timeval now;
280 		double delay;
281 		ortp_gettimeofday(&now,NULL);
282 		delay= (now.tv_sec-stream->last_rcv_SR_time.tv_sec)+ ((now.tv_usec-stream->last_rcv_SR_time.tv_usec)*1e-6);
283 		delay= (delay*65536);
284 		delay_snc_last_sr=(uint32_t) delay;
285 	}
286 
287 	b->ssrc=htonl(session->rcv.ssrc);
288 
289 
290 	report_block_set_cum_packet_lost(b, session->stats.cum_packet_loss);
291 	report_block_set_fraction_lost(b, loss_fraction);
292 
293 	if ( session->flags & RTCP_OVERRIDE_JITTER ) {
294 		/* If the test mode is enabled, replace the interarrival jitter field with the test vector value set by rtp_session_rtcp_set_jitter_value() */
295 		b->interarrival_jitter = htonl( session->interarrival_jitter_test_vector );
296 	}
297 	else {
298 		/* Normal mode */
299 		b->interarrival_jitter = htonl( (uint32_t) stream->jittctl.inter_jitter );
300 	}
301 	b->ext_high_seq_num_rec=htonl(stream->hwrcv_extseq);
302 	b->delay_snc_last_sr=htonl(delay_snc_last_sr);
303 	if ( session->flags & RTCP_OVERRIDE_DELAY ) {
304 		/* If the test mode is enabled, modifies the returned ts (LSR) so it matches the value of the delay test value */
305 		/* refer to the rtp_session_rtcp_set_delay_value() documentation for further explanations */
306 		double new_ts = ( (double)stream->last_rcv_SR_time.tv_sec + (double)stream->last_rcv_SR_time.tv_usec * 1e-6 ) - ( (double)session->delay_test_vector / 1000.0 );
307 		uint32_t new_ts2;
308 
309 		/* Converting the time format in RFC3550 (par. 4) format */
310 		new_ts += 2208988800.0; /* 2208988800 is the number of seconds from 1900 to 1970 (January 1, Oh TU) */
311 		new_ts = 65536.0 * new_ts;
312 		/* This non-elegant way of coding fits with the gcc and the icc compilers */
313 		new_ts2 = (uint32_t)( (uint64_t)new_ts & 0xffffffff );
314 		b->lsr = htonl( new_ts2 );
315 	}
316 	else {
317 		/* Normal mode */
318 		b->lsr = htonl( stream->last_rcv_SR_ts );
319 	}
320 }
321 
extended_statistics(RtpSession * session,report_block_t * rb)322 static void extended_statistics( RtpSession *session, report_block_t * rb ) {
323 	/* the jitter raw value is kept in stream clock units */
324 	uint32_t jitter = (uint32_t)session->rtp.jittctl.inter_jitter;
325 	session->stats.sent_rtcp_packets ++;
326 	session->rtp.jitter_stats.sum_jitter += jitter;
327 	session->rtp.jitter_stats.jitter=jitter;
328 	/* stores the biggest jitter for that session and its date (in millisecond) since Epoch */
329 	if ( jitter > session->rtp.jitter_stats.max_jitter ) {
330 		struct timeval now;
331 
332 		session->rtp.jitter_stats.max_jitter = jitter ;
333 
334 		ortp_gettimeofday( &now, NULL );
335 		session->rtp.jitter_stats.max_jitter_ts = ( now.tv_sec * 1000LL ) + ( now.tv_usec / 1000LL );
336 	}
337 	/* compute mean jitter buffer size */
338 	session->rtp.jitter_stats.jitter_buffer_size_ms=jitter_control_compute_mean_size(&session->rtp.jittctl);
339 }
340 
rtcp_sr_init(RtpSession * session,uint8_t * buf,size_t size)341 static size_t rtcp_sr_init(RtpSession *session, uint8_t *buf, size_t size){
342 	rtcp_sr_t *sr=(rtcp_sr_t*)buf;
343 	int rr=(session->stats.packet_recv>0);
344 	size_t sr_size=sizeof(rtcp_sr_t)-sizeof(report_block_t)+(rr*sizeof(report_block_t));
345 	if (size<sr_size) return 0;
346 	rtcp_common_header_init(&sr->ch,session,RTCP_SR,rr,sr_size);
347 	sr->ssrc=htonl(session->snd.ssrc);
348 	sender_info_init(&sr->si,session);
349 	/*only include a report block if packets were received*/
350 	if (rr) {
351 		report_block_init( &sr->rb[0], session );
352 		extended_statistics( session, &sr->rb[0] );
353 	}
354 	return sr_size;
355 }
356 
rtcp_rr_init(RtpSession * session,uint8_t * buf,size_t size)357 static size_t rtcp_rr_init(RtpSession *session, uint8_t *buf, size_t size){
358 	rtcp_rr_t *rr=(rtcp_rr_t*)buf;
359 	if (size<sizeof(rtcp_rr_t)) return 0;
360 	rtcp_common_header_init(&rr->ch,session,RTCP_RR,1,sizeof(rtcp_rr_t));
361 	rr->ssrc=htonl(session->snd.ssrc);
362 	report_block_init(&rr->rb[0],session);
363 	extended_statistics( session, &rr->rb[0] );
364 	return sizeof(rtcp_rr_t);
365 }
366 
rtcp_app_init(RtpSession * session,uint8_t * buf,uint8_t subtype,const char * name,size_t size)367 static size_t rtcp_app_init(RtpSession *session, uint8_t *buf, uint8_t subtype, const char *name, size_t size){
368 	rtcp_app_t *app=(rtcp_app_t*)buf;
369 	if (size<sizeof(rtcp_app_t)) return 0;
370 	rtcp_common_header_init(&app->ch,session,RTCP_APP,subtype,size);
371 	app->ssrc=htonl(session->snd.ssrc);
372 	memset(app->name,0,4);
373 	strncpy(app->name,name,4);
374 	return sizeof(rtcp_app_t);
375 }
376 
make_rr(RtpSession * session)377 static mblk_t * make_rr(RtpSession *session) {
378 	mblk_t *cm = allocb(sizeof(rtcp_sr_t), 0);
379 	cm->b_wptr += rtcp_rr_init(session, cm->b_wptr, sizeof(rtcp_rr_t));
380 	return cm;
381 }
382 
make_sr(RtpSession * session)383 static mblk_t * make_sr(RtpSession *session) {
384 	mblk_t *cm = allocb(sizeof(rtcp_sr_t), 0);
385 	cm->b_wptr += rtcp_sr_init(session, cm->b_wptr, sizeof(rtcp_sr_t));
386 	return cm;
387 }
388 
append_sdes(RtpSession * session,mblk_t * m,bool_t full)389 static mblk_t * append_sdes(RtpSession *session, mblk_t *m, bool_t full) {
390 	mblk_t *sdes = NULL;
391 
392 	if ((full == TRUE) && (session->full_sdes != NULL)) {
393 		sdes = rtp_session_create_rtcp_sdes_packet(session, full);
394 	} else if ((full == FALSE) && (session->minimal_sdes != NULL)) {
395 		sdes = rtp_session_create_rtcp_sdes_packet(session, full);
396 	}
397 	return concatb(m, sdes);
398 }
399 
notify_sent_rtcp(RtpSession * session,mblk_t * rtcp)400 static void notify_sent_rtcp(RtpSession *session, mblk_t *rtcp){
401 	if (session->eventqs!=NULL){
402 		OrtpEvent *ev;
403 		OrtpEventData *evd;
404 		ev=ortp_event_new(ORTP_EVENT_RTCP_PACKET_EMITTED);
405 		evd=ortp_event_get_data(ev);
406 		evd->packet=dupmsg(rtcp);
407 		msgpullup(evd->packet,-1);
408 		rtp_session_dispatch_event(session,ev);
409 	}
410 }
411 
append_xr_packets(RtpSession * session,mblk_t * m)412 static void append_xr_packets(RtpSession *session, mblk_t *m) {
413 	if (session->rtcp.xr_conf.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) {
414 		concatb(m, make_xr_rcvr_rtt(session));
415 	}
416 	if (session->rtcp.rtcp_xr_dlrr_to_send == TRUE) {
417 		concatb(m, make_xr_dlrr(session));
418 		session->rtcp.rtcp_xr_dlrr_to_send = FALSE;
419 	}
420 	if (session->rtcp.xr_conf.stat_summary_enabled == TRUE) {
421 		concatb(m, make_xr_stat_summary(session));
422 	}
423 	if (session->rtcp.xr_conf.voip_metrics_enabled == TRUE) {
424 		concatb(m, make_xr_voip_metrics(session));
425 	}
426 }
427 
append_fb_packets(RtpSession * session,mblk_t * m)428 static void append_fb_packets(RtpSession *session, mblk_t *m) {
429 	if (session->rtcp.send_algo.fb_packets != NULL) {
430 		concatb(m, session->rtcp.send_algo.fb_packets);
431 		session->rtcp.send_algo.fb_packets = NULL;
432 	}
433 
434 	/* Repeat TMMBR packets until they are acknowledged with a TMMBN unless a TMMBN is being sent. */
435 	if (rtp_session_avpf_feature_enabled(session, ORTP_AVPF_FEATURE_TMMBR)
436 		&& (session->rtcp.tmmbr_info.sent != NULL)
437 		&& (session->rtcp.send_algo.tmmbr_scheduled != TRUE)
438 		&& (session->rtcp.send_algo.tmmbn_scheduled != TRUE)) {
439 		concatb(m, copymsg(session->rtcp.tmmbr_info.sent));
440 	}
441 
442 	session->rtcp.send_algo.tmmbr_scheduled = FALSE;
443 	session->rtcp.send_algo.tmmbn_scheduled = FALSE;
444 }
445 
rtp_session_create_and_send_rtcp_packet(RtpSession * session,bool_t full)446 static void rtp_session_create_and_send_rtcp_packet(RtpSession *session, bool_t full) {
447 	mblk_t *m=NULL;
448 	bool_t is_sr = FALSE;
449 
450 	if (session->rtp.last_rtcp_packet_count < session->stats.packet_sent) {
451 		m = make_sr(session);
452 		session->rtp.last_rtcp_packet_count = (uint32_t)session->stats.packet_sent;
453 		is_sr = TRUE;
454 	} else if (session->stats.packet_recv > 0) {
455 		/* Don't send RR when no packet are received yet */
456 		m = make_rr(session);
457 		is_sr = FALSE;
458 	}
459 	if (m != NULL) {
460 		append_sdes(session, m, full);
461 		if ((full == TRUE) && (session->rtcp.xr_conf.enabled == TRUE)) {
462 			append_xr_packets(session, m);
463 		}
464 		if (rtp_session_avpf_enabled(session) == TRUE) {
465 			append_fb_packets(session, m);
466 		}
467 		/* Send the compound packet */
468 		notify_sent_rtcp(session, m);
469 		ortp_message("Sending RTCP %s compound message on session [%p].",(is_sr ? "SR" : "RR"), session);
470 		rtp_session_rtcp_send(session, m);
471 	}
472 }
473 
rtcp_rand(float t)474 static float rtcp_rand(float t) {
475 	return t * ((rand() / (RAND_MAX * 1.0f)) + 0.5f);
476 }
477 
478 /**
479  * This is a simplified version with this limit of the algorithm described in
480  * the appendix A.7 of RFC3550.
481  */
compute_rtcp_interval(RtpSession * session)482 void compute_rtcp_interval(RtpSession *session) {
483 	float t;
484 	float rtcp_min_time;
485 	float rtcp_bw;
486 
487 	if (session->target_upload_bandwidth == 0) return;
488 
489 	/* Compute target RTCP bandwidth in bits/s. */
490 	rtcp_bw = 0.05f * session->target_upload_bandwidth;
491 
492 	if (rtp_session_avpf_enabled(session) == TRUE) {
493 		session->rtcp.send_algo.T_rr_interval = rtp_session_get_avpf_rr_interval(session);
494 		rtcp_min_time = (float)session->rtcp.send_algo.Tmin;
495 	} else {
496 		rtcp_min_time = (float)session->rtcp.send_algo.T_rr_interval;
497 		if (session->rtcp.send_algo.initial == TRUE) {
498 			rtcp_min_time /= 2.;
499 		}
500 	}
501 
502 	t = ((session->rtcp.send_algo.avg_rtcp_size * 8 * 2) / rtcp_bw) * 1000;
503 	if (t < rtcp_min_time) t = rtcp_min_time;
504 	t = rtcp_rand(t);
505 	t = t / (2.71828f - 1.5f); /* Compensation */
506 	session->rtcp.send_algo.T_rr = (uint32_t)t;
507 }
508 
update_avg_rtcp_size(RtpSession * session,int bytes)509 void update_avg_rtcp_size(RtpSession *session, int bytes) {
510 	int overhead = (ortp_stream_is_ipv6(&session->rtcp.gs) == TRUE) ? IP6_UDP_OVERHEAD : IP_UDP_OVERHEAD;
511 	int size = bytes + overhead;
512 	session->rtcp.send_algo.avg_rtcp_size = ((size + (15 * session->rtcp.send_algo.avg_rtcp_size)) / 16.f);
513 }
514 
rtp_session_schedule_first_rtcp_send(RtpSession * session)515 static void rtp_session_schedule_first_rtcp_send(RtpSession *session) {
516 	uint64_t tc;
517 	size_t overhead;
518 	size_t report_size;
519 	size_t sdes_size;
520 	size_t xr_size = 0;
521 	OrtpRtcpSendAlgorithm *sa = &session->rtcp.send_algo;
522 
523 	if ((session->rtcp.enabled == FALSE) || (session->target_upload_bandwidth == 0) || (sa->initialized == TRUE))
524 		return;
525 
526 	overhead = (ortp_stream_is_ipv6(&session->rtcp.gs) == TRUE) ? IP6_UDP_OVERHEAD : IP_UDP_OVERHEAD;
527 	sdes_size = (session->full_sdes != NULL) ? msgdsize(session->full_sdes) + sizeof(rtcp_common_header_t) : 0;
528 	switch (session->mode) {
529 		case RTP_SESSION_RECVONLY:
530 			report_size = sizeof(rtcp_rr_t);
531 			break;
532 		case RTP_SESSION_SENDONLY:
533 			report_size = sizeof(rtcp_sr_t) - sizeof(report_block_t);
534 			break;
535 		case RTP_SESSION_SENDRECV:
536 		default:
537 			report_size = sizeof(rtcp_sr_t);
538 			break;
539 	}
540 	if (session->rtcp.xr_conf.enabled == TRUE) {
541 		if (session->rtcp.xr_conf.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone)
542 			xr_size += sizeof(rtcp_xr_header_t) + sizeof(rtcp_xr_rcvr_rtt_report_block_t);
543 		if (session->rtcp.xr_conf.stat_summary_enabled == TRUE)
544 			xr_size += sizeof(rtcp_xr_header_t) + sizeof(rtcp_xr_stat_summary_report_block_t);
545 		if (session->rtcp.xr_conf.voip_metrics_enabled == TRUE)
546 			xr_size += sizeof(rtcp_xr_header_t) + sizeof(rtcp_xr_voip_metrics_report_block_t);
547 	}
548 	sa->avg_rtcp_size = (float)(overhead + report_size + sdes_size + xr_size);
549 	sa->initialized = TRUE;
550 
551 	tc = ortp_get_cur_time_ms();
552 	compute_rtcp_interval(session);
553 	if (sa->T_rr > 0) sa->tn = tc + sa->T_rr;
554 	sa->tp = tc;
555 	sa->t_rr_last = tc;
556 	sa->Tmin = 0;
557 }
558 
rtp_session_reschedule(RtpSession * session,uint64_t tc)559 static void rtp_session_reschedule(RtpSession *session, uint64_t tc) {
560 	OrtpRtcpSendAlgorithm *sa = &session->rtcp.send_algo;
561 	if (rtp_session_avpf_enabled(session) == TRUE) {
562 		sa->tp = tc;
563 		sa->tn = tc + sa->T_rr;
564 	}
565 }
566 
rtp_session_send_regular_rtcp_packet_and_reschedule(RtpSession * session,uint64_t tc)567 void rtp_session_send_regular_rtcp_packet_and_reschedule(RtpSession *session, uint64_t tc) {
568 	OrtpRtcpSendAlgorithm *sa = &session->rtcp.send_algo;
569 	rtp_session_create_and_send_rtcp_packet(session, TRUE);
570 	sa->tp = tc;
571 	sa->t_rr_last = sa->tn;
572 	compute_rtcp_interval(session);
573 	sa->tn = tc + sa->T_rr;
574 	sa->initial = FALSE;
575 }
576 
rtp_session_send_fb_rtcp_packet_and_reschedule(RtpSession * session)577 void rtp_session_send_fb_rtcp_packet_and_reschedule(RtpSession *session) {
578 	uint64_t previous_tn;
579 	OrtpRtcpSendAlgorithm *sa = &session->rtcp.send_algo;
580 	rtp_session_create_and_send_rtcp_packet(session, FALSE);
581 	sa->allow_early = FALSE;
582 	previous_tn = sa->tn;
583 	sa->tn = sa->tp + 2 * sa->T_rr;
584 	sa->tp = previous_tn;
585 }
586 
rtp_session_run_rtcp_send_scheduler(RtpSession * session)587 void rtp_session_run_rtcp_send_scheduler(RtpSession *session) {
588 	uint64_t tc = ortp_get_cur_time_ms();
589 	OrtpRtcpSendAlgorithm *sa = &session->rtcp.send_algo;
590 
591 	if (tc >= sa->tn) {
592 		compute_rtcp_interval(session);
593 		sa->tn = sa->tp + sa->T_rr;
594 		if (tc >= sa->tn) {
595 			if (sa->t_rr_last == 0) {
596 				rtp_session_schedule_first_rtcp_send(session);
597 			} else {
598 				if (sa->T_rr_interval != 0) {
599 					sa->T_rr_current_interval = (uint32_t)rtcp_rand((float)sa->T_rr_interval);
600 				} else {
601 					sa->T_rr_current_interval = 0;
602 				}
603 				if (sa->tn >= (sa->t_rr_last + sa->T_rr_current_interval)) {
604 					rtp_session_send_regular_rtcp_packet_and_reschedule(session, tc);
605 				} else if (rtp_session_has_fb_packets_to_send(session) == TRUE) {
606 					rtp_session_send_fb_rtcp_packet_and_reschedule(session);
607 				} else {
608 					rtp_session_reschedule(session, tc);
609 				}
610 			}
611 		}
612 	}
613 }
614 
rtp_session_rtcp_process_send(RtpSession * session)615 void rtp_session_rtcp_process_send(RtpSession *session) {
616 	rtp_session_run_rtcp_send_scheduler(session);
617 }
618 
rtp_session_rtcp_process_recv(RtpSession * session)619 void rtp_session_rtcp_process_recv(RtpSession *session){
620 	rtp_session_run_rtcp_send_scheduler(session);
621 }
622 
rtp_session_send_rtcp_APP(RtpSession * session,uint8_t subtype,const char * name,const uint8_t * data,int datalen)623 void rtp_session_send_rtcp_APP(RtpSession *session, uint8_t subtype, const char *name, const uint8_t *data, int datalen){
624 	mblk_t *h=allocb(sizeof(rtcp_app_t),0);
625 	mblk_t *d;
626 	h->b_wptr+=rtcp_app_init(session,h->b_wptr,subtype,name,datalen+sizeof(rtcp_app_t));
627 	d=esballoc((uint8_t*)data,datalen,0,NULL);
628 	d->b_wptr+=datalen;
629 	h->b_cont=d;
630 	rtp_session_rtcp_send(session,h);
631 }
632 
633 /**
634  * Sends a RTCP bye packet.
635  *@param session RtpSession
636  *@param reason the reason phrase.
637 **/
rtp_session_bye(RtpSession * session,const char * reason)638 int rtp_session_bye(RtpSession *session, const char *reason) {
639     mblk_t *cm;
640     mblk_t *sdes = NULL;
641     mblk_t *bye = NULL;
642     int ret;
643 
644     /* Make a BYE packet (will be on the end of the compund packet). */
645     bye = rtcp_create_simple_bye_packet(session->snd.ssrc, reason);
646 
647     /* SR or RR is determined by the fact whether stream was sent*/
648     if (session->stats.packet_sent>0)
649     {
650         cm = allocb(sizeof(rtcp_sr_t), 0);
651         cm->b_wptr += rtcp_sr_init(session,cm->b_wptr, sizeof(rtcp_sr_t));
652         /* make a SDES packet */
653         sdes = rtp_session_create_rtcp_sdes_packet(session, TRUE);
654         /* link them */
655         concatb(concatb(cm, sdes), bye);
656     } else if (session->stats.packet_recv>0){
657         /* make a RR packet */
658         cm = allocb(sizeof(rtcp_rr_t), 0);
659         cm->b_wptr += rtcp_rr_init(session, cm->b_wptr, sizeof(rtcp_rr_t));
660         /* link them */
661         cm->b_cont = bye;
662     }else cm=bye;
663 
664     /* Send compound packet. */
665     ret = rtp_session_rtcp_send(session, cm);
666 
667     return ret;
668 }
669 
ortp_loss_rate_estimator_new(int min_packet_count_interval,uint64_t min_time_ms_interval,RtpSession * session)670 OrtpLossRateEstimator * ortp_loss_rate_estimator_new(int min_packet_count_interval, uint64_t min_time_ms_interval, RtpSession *session){
671 	OrtpLossRateEstimator *obj=ortp_malloc(sizeof(OrtpLossRateEstimator));
672 	ortp_loss_rate_estimator_init(obj,min_packet_count_interval, min_time_ms_interval, session);
673 	return obj;
674 }
675 
ortp_loss_rate_estimator_init(OrtpLossRateEstimator * obj,int min_packet_count_interval,uint64_t min_time_ms_interval,RtpSession * session)676 void ortp_loss_rate_estimator_init(OrtpLossRateEstimator *obj, int min_packet_count_interval, uint64_t min_time_ms_interval, RtpSession *session){
677 	memset(obj,0,sizeof(*obj));
678 	obj->min_packet_count_interval=min_packet_count_interval;
679 	obj->last_ext_seq=rtp_session_get_seq_number(session);
680 	obj->last_cum_loss=rtp_session_get_cum_loss(session);
681 	obj->last_packet_sent_count=session->stats.packet_sent;
682 	obj->last_dup_packet_sent_count=session->stats.packet_dup_sent;
683 	obj->min_time_ms_interval=min_time_ms_interval;
684 	obj->last_estimate_time_ms=(uint64_t)-1;
685 }
686 
ortp_loss_rate_estimator_process_report_block(OrtpLossRateEstimator * obj,const RtpSession * session,const report_block_t * rb)687 bool_t ortp_loss_rate_estimator_process_report_block(OrtpLossRateEstimator *obj, const RtpSession *session, const report_block_t *rb){
688 	int32_t cum_loss=report_block_get_cum_packet_lost(rb);
689 	int32_t extseq=report_block_get_high_ext_seq(rb);
690 	//int32_t diff_unique_outgoing=(int32_t)(session->stats.packet_sent-obj->last_packet_sent_count);
691 	//int32_t diff_total_outgoing=diff_unique_outgoing+(int32_t)(session->stats.packet_dup_sent-obj->last_dup_packet_sent_count);
692 	int32_t diff;
693 	uint64_t curtime;
694 	bool_t got_value=FALSE;
695 
696 	if (obj->last_ext_seq==-1 || obj->last_estimate_time_ms==(uint64_t)-1){
697 		/*first report cannot be considered, since we don't know the interval it covers*/
698 		obj->last_ext_seq=extseq;
699 		obj->last_cum_loss=cum_loss;
700 		obj->last_estimate_time_ms=ortp_get_cur_time_ms();
701 		return FALSE;
702 	}
703 	diff=extseq-obj->last_ext_seq;
704 	curtime=ortp_get_cur_time_ms();
705 	if (diff<0 || diff>obj->min_packet_count_interval * 100){
706 		if (extseq==0){
707 			/*when extseq reset to 0, it probably means that rtp_session_sync was called but
708 			since OrtplossRateEstimator is not reset, first RTCP packet received will be detected
709 			as discontinuity instead of init RTCP packet. Avoid logging in such case.*/
710 			ortp_message("ortp_loss_rate_estimator_process %p: Suspected RTP session restart, sequence numbering from %d to %d.", obj, obj->last_ext_seq, extseq);
711 		}else{
712 			ortp_warning("ortp_loss_rate_estimator_process %p: Suspected discontinuity in sequence numbering from %d to %d.", obj, obj->last_ext_seq, extseq);
713 		}
714 		obj->last_ext_seq=extseq;
715 		obj->last_cum_loss=cum_loss;
716 		obj->last_packet_sent_count=session->stats.packet_sent;
717 		obj->last_dup_packet_sent_count=session->stats.packet_dup_sent;
718 	}else if (diff>obj->min_packet_count_interval && curtime-obj->last_estimate_time_ms>=obj->min_time_ms_interval){
719 		/*we have sufficient interval*/
720 		int32_t new_losses=cum_loss-obj->last_cum_loss;
721 
722 #if 0 /*SM: the following code try to takes into account sent duplicates - however by doing this it creates a bias in the loss rate computation
723 		that can sometimes result in a negative loss rate, even if there is no duplicate.
724 		Since the rate control doesn't use duplicates anymore, there is no good reason to take this into account.
725 		*/
726 		/*if we are using duplicates, they will not be visible in 'diff' variable.
727 		But since we are the emitter, we can retrieve the total count of packet we
728 		sent and use this value to compute the loss rate instead.*/
729 		obj->loss_rate = 100.f * (1.f - MAX(0, (diff_unique_outgoing - new_losses) * 1.f / diff_total_outgoing));
730 #endif
731 		obj->loss_rate = 100.f * (float) new_losses / (float)( extseq - obj->last_ext_seq);
732 
733 		/*update last values with current*/
734 		got_value=TRUE;
735 		obj->last_estimate_time_ms=curtime;
736 
737 		if (obj->loss_rate>100.f){
738 			obj->loss_rate = 100.f;
739 			ortp_error("ortp_loss_rate_estimator_process %p: Loss rate MUST NOT be greater than 100%%", obj);
740 		}else if(obj->loss_rate < 0){
741 			obj->loss_rate = 0;
742 			ortp_error("ortp_loss_rate_estimator_process %p: Loss rate MUST NOT be negative", obj);
743 		}
744 		obj->last_ext_seq=extseq;
745 		obj->last_cum_loss=cum_loss;
746 		obj->last_packet_sent_count=session->stats.packet_sent;
747 		obj->last_dup_packet_sent_count=session->stats.packet_dup_sent;
748 	}
749 	return got_value;
750 
751 }
752 
ortp_loss_rate_estimator_get_value(OrtpLossRateEstimator * obj)753 float ortp_loss_rate_estimator_get_value(OrtpLossRateEstimator *obj){
754 	return obj->loss_rate;
755 }
756 
ortp_loss_rate_estimator_destroy(OrtpLossRateEstimator * obj)757 void ortp_loss_rate_estimator_destroy(OrtpLossRateEstimator *obj){
758 	ortp_free(obj);
759 }
760