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 #include "ortp/ortp.h"
22 #include "utils.h"
23 
rtcp_get_size(const mblk_t * m)24 static size_t rtcp_get_size(const mblk_t *m){
25 	const rtcp_common_header_t *ch=rtcp_get_common_header(m);
26 	if (ch==NULL) return 0;
27 	return (1+rtcp_common_header_get_length(ch))*4;
28 }
29 
30 /*in case of compound packet, set read pointer of m to the beginning of the next RTCP
31 packet */
rtcp_next_packet(mblk_t * m)32 bool_t rtcp_next_packet(mblk_t *m){
33 	size_t nextlen=rtcp_get_size(m);
34 	if ((nextlen > 0) && (m->b_rptr + nextlen < m->b_wptr)){
35 		m->b_rptr+=nextlen;
36 		return TRUE;
37 	}
38 	return FALSE;
39 }
40 
rtcp_rewind(mblk_t * m)41 void rtcp_rewind(mblk_t *m){
42 	m->b_rptr=m->b_datap->db_base;
43 }
44 
45 /* get common header; this function will also check the sanity of the packet*/
rtcp_get_common_header(const mblk_t * m)46 const rtcp_common_header_t * rtcp_get_common_header(const mblk_t *m){
47 	size_t size=msgdsize(m);
48 	rtcp_common_header_t *ch;
49 	if (m->b_cont!=NULL){
50 		ortp_fatal("RTCP parser does not work on fragmented mblk_t. Use msgpullup() before to re-assemble the packet.");
51 		return NULL;
52 	}
53 	if (size<sizeof(rtcp_common_header_t)){
54 		ortp_warning("Bad RTCP packet, too short [%i b]. on block [%p]",(int)size,m);
55 		return NULL;
56 	}
57 	ch=(rtcp_common_header_t*)m->b_rptr;
58 	return ch;
59 }
60 
rtcp_is_SR(const mblk_t * m)61 bool_t rtcp_is_SR(const mblk_t *m){
62 	const rtcp_common_header_t *ch=rtcp_get_common_header(m);
63 	if (ch!=NULL && rtcp_common_header_get_packet_type(ch)==RTCP_SR){
64 		if (msgdsize(m)<(sizeof(rtcp_sr_t)-sizeof(report_block_t))){
65 			ortp_warning("Too short RTCP SR packet.");
66 			return FALSE;
67 		}
68 		return TRUE;
69 	}
70 	return FALSE;
71 }
72 
73 /*Sender Report accessors */
rtcp_SR_get_ssrc(const mblk_t * m)74 uint32_t rtcp_SR_get_ssrc(const mblk_t *m){
75 	rtcp_sr_t *sr=(rtcp_sr_t*)m->b_rptr;
76 	return ntohl(sr->ssrc);
77 }
78 
rtcp_SR_get_sender_info(const mblk_t * m)79 const sender_info_t * rtcp_SR_get_sender_info(const mblk_t *m){
80 	rtcp_sr_t *sr=(rtcp_sr_t*)m->b_rptr;
81 	return &sr->si;
82 }
83 
rtcp_SR_get_report_block(const mblk_t * m,int idx)84 const report_block_t * rtcp_SR_get_report_block(const mblk_t *m, int idx){
85 	rtcp_sr_t *sr=(rtcp_sr_t*)m->b_rptr;
86 	report_block_t *rb=&sr->rb[idx];
87 	size_t size=rtcp_get_size(m);
88 	if ( ( (uint8_t*)rb)+sizeof(report_block_t) <= m->b_rptr + size ) {
89 		return rb;
90 	}else{
91 		if (idx<rtcp_common_header_get_rc(&sr->ch)){
92 			ortp_warning("RTCP packet should include a report_block_t at pos %i but has no space for it.",idx);
93 		}
94 	}
95 	return NULL;
96 }
97 
98 /*Receiver report accessors*/
rtcp_is_RR(const mblk_t * m)99 bool_t rtcp_is_RR(const mblk_t *m){
100 	const rtcp_common_header_t *ch=rtcp_get_common_header(m);
101 	if (ch!=NULL && rtcp_common_header_get_packet_type(ch)==RTCP_RR){
102 		if (msgdsize(m)<sizeof(rtcp_rr_t)){
103 			ortp_warning("Too short RTCP RR packet.");
104 			return FALSE;
105 		}
106 		return TRUE;
107 	}
108 	return FALSE;
109 }
110 
rtcp_RR_get_ssrc(const mblk_t * m)111 uint32_t rtcp_RR_get_ssrc(const mblk_t *m){
112 	rtcp_rr_t *rr=(rtcp_rr_t*)m->b_rptr;
113 	return ntohl(rr->ssrc);
114 }
115 
rtcp_RR_get_report_block(const mblk_t * m,int idx)116 const report_block_t * rtcp_RR_get_report_block(const mblk_t *m,int idx){
117 	rtcp_rr_t *rr=(rtcp_rr_t*)m->b_rptr;
118 	report_block_t *rb=&rr->rb[idx];
119 	size_t size=rtcp_get_size(m);
120 	if ( ( (uint8_t*)rb)+sizeof(report_block_t) <= (m->b_rptr + size ) ){
121 		return rb;
122 	}else{
123 		if (idx<rtcp_common_header_get_rc(&rr->ch)){
124 			ortp_warning("RTCP packet should include a report_block_t at pos %i but has no space for it.",idx);
125 		}
126 	}
127 	return NULL;
128 }
129 
130 /*SDES accessors */
rtcp_is_SDES(const mblk_t * m)131 bool_t rtcp_is_SDES(const mblk_t *m){
132 	const rtcp_common_header_t *ch=rtcp_get_common_header(m);
133 	if (ch && rtcp_common_header_get_packet_type(ch)==RTCP_SDES){
134 		if (msgdsize(m)<rtcp_get_size(m)){
135 			ortp_warning("Too short RTCP SDES packet.");
136 			return FALSE;
137 		}
138 		return TRUE;
139 	}
140 	return FALSE;
141 }
142 
rtcp_sdes_parse(const mblk_t * m,SdesItemFoundCallback cb,void * user_data)143 void rtcp_sdes_parse(const mblk_t *m, SdesItemFoundCallback cb, void *user_data){
144 	uint8_t *rptr=(uint8_t*)m->b_rptr+sizeof(rtcp_common_header_t);
145 	const rtcp_common_header_t *ch=(rtcp_common_header_t*)m->b_rptr;
146 	uint8_t *end=rptr+(4*(rtcp_common_header_get_length(ch)+1));
147 	uint32_t ssrc=0;
148 	int nchunk=0;
149 	bool_t chunk_start=TRUE;
150 
151 	if (end>(uint8_t*)m->b_wptr) end=(uint8_t*)m->b_wptr;
152 
153 	while(rptr<end){
154 		if (chunk_start){
155 			if (rptr+4<=end){
156 				ssrc=ntohl(*(uint32_t*)rptr);
157 				rptr+=4;
158 			}else{
159 				ortp_warning("incorrect chunk start in RTCP SDES");
160 				break;
161 			}
162 			chunk_start=FALSE;
163 		}else{
164 			if (rptr+2<=end){
165 				uint8_t type=rptr[0];
166 				uint8_t len=rptr[1];
167 
168 				if (type==RTCP_SDES_END){
169 					/* pad to next 32bit boundary*/
170 					rptr=(uint8_t *)((intptr_t)(rptr+4) & ~0x3);
171 					nchunk++;
172 					if (nchunk<rtcp_common_header_get_rc(ch)){
173 						chunk_start=TRUE;
174 						continue;
175 					}else break;
176 				}
177 				rptr+=2;
178 				if (rptr+len<=end){
179 					cb(user_data,ssrc,type,(char*)rptr,len);
180 					rptr+=len;
181 				}else{
182 					ortp_warning("bad item length in RTCP SDES");
183 					break;
184 				}
185 			}else{
186 				/*end of packet */
187 				break;
188 			}
189 		}
190 	}
191 }
192 
193 /*BYE accessors */
rtcp_is_BYE(const mblk_t * m)194 bool_t rtcp_is_BYE(const mblk_t *m){
195 	const rtcp_common_header_t *ch=rtcp_get_common_header(m);
196 	if (ch && rtcp_common_header_get_packet_type(ch)==RTCP_BYE){
197 		if (msgdsize(m)<rtcp_get_size(m)){
198 			ortp_warning("Too short RTCP BYE packet.");
199 			return FALSE;
200 		}
201 		return TRUE;
202 	}
203 	return FALSE;
204 }
205 
rtcp_BYE_get_ssrc(const mblk_t * m,int idx,uint32_t * ssrc)206 bool_t rtcp_BYE_get_ssrc(const mblk_t *m, int idx, uint32_t *ssrc){
207 	rtcp_bye_t *bye=(rtcp_bye_t*)m->b_rptr;
208 	int rc=rtcp_common_header_get_rc(&bye->ch);
209 	if (idx<rc){
210 		if ((uint8_t*)&bye->ssrc[idx]<=(m->b_rptr
211 				+ rtcp_get_size(m)-4)) {
212 			*ssrc=ntohl(bye->ssrc[idx]);
213 			return TRUE;
214 		}else{
215 			ortp_warning("RTCP BYE should contain %i ssrc, but there is not enough room for it.",rc);
216 		}
217 	}
218 	return FALSE;
219 }
220 
rtcp_BYE_get_reason(const mblk_t * m,const char ** reason,int * reason_len)221 bool_t rtcp_BYE_get_reason(const mblk_t *m, const char **reason, int *reason_len){
222 	rtcp_bye_t *bye=(rtcp_bye_t*)m->b_rptr;
223 	int rc=rtcp_common_header_get_rc(&bye->ch);
224 	uint8_t *rptr=(uint8_t*)m->b_rptr+sizeof(rtcp_common_header_t)+rc*4;
225 	uint8_t *end=(uint8_t*)(m->b_rptr+rtcp_get_size(m));
226 	if (rptr<end){
227 		uint8_t content_len=rptr[0];
228 		if (rptr+1+content_len<=end){
229 			*reason=(char*)rptr+1;
230 			*reason_len=content_len;
231 			return TRUE;
232 		}else{
233 			ortp_warning("RTCP BYE has not enough space for reason phrase.");
234 			return FALSE;
235 		}
236 	}
237 	return FALSE;
238 }
239 
240 /*APP accessors */
rtcp_is_APP(const mblk_t * m)241 bool_t rtcp_is_APP(const mblk_t *m){
242 	const rtcp_common_header_t *ch=rtcp_get_common_header(m);
243 	size_t size=rtcp_get_size(m);
244 	if (ch!=NULL && rtcp_common_header_get_packet_type(ch)==RTCP_APP){
245 		if (msgdsize(m)<size){
246 			ortp_warning("Too short RTCP APP packet.");
247 			return FALSE;
248 		}
249 		if (size < sizeof(rtcp_app_t)){
250 			ortp_warning("Bad RTCP APP packet.");
251 			return FALSE;
252 		}
253 		return TRUE;
254 	}
255 	return FALSE;
256 }
257 
rtcp_APP_get_subtype(const mblk_t * m)258 int rtcp_APP_get_subtype(const mblk_t *m){
259 	rtcp_app_t *app=(rtcp_app_t*)m->b_rptr;
260 	return rtcp_common_header_get_rc(&app->ch);
261 }
262 
rtcp_APP_get_ssrc(const mblk_t * m)263 uint32_t rtcp_APP_get_ssrc(const mblk_t *m){
264 	rtcp_app_t *app=(rtcp_app_t*)m->b_rptr;
265 	return ntohl(app->ssrc);
266 }
267 /* name argument is supposed to be at least 4 characters (note: no '\0' written)*/
rtcp_APP_get_name(const mblk_t * m,char * name)268 void rtcp_APP_get_name(const mblk_t *m, char *name){
269 	rtcp_app_t *app=(rtcp_app_t*)m->b_rptr;
270 	memcpy(name,app->name,4);
271 }
272 /* retrieve the data. when returning, data points directly into the mblk_t */
rtcp_APP_get_data(const mblk_t * m,uint8_t ** data,int * len)273 void rtcp_APP_get_data(const mblk_t *m, uint8_t **data, int *len){
274 	int datalen=(int)rtcp_get_size(m)-sizeof(rtcp_app_t);
275 	if (datalen>0){
276 		*data=(uint8_t*)m->b_rptr+sizeof(rtcp_app_t);
277 		*len=datalen;
278 	}else{
279 		*len=0;
280 		*data=NULL;
281 	}
282 }
283 
284 
285 /* RTCP XR accessors */
rtcp_is_XR(const mblk_t * m)286 bool_t rtcp_is_XR(const mblk_t *m) {
287 	const rtcp_common_header_t *ch = rtcp_get_common_header(m);
288 	if ((ch != NULL) && (rtcp_common_header_get_packet_type(ch) == RTCP_XR)) {
289 		if (msgdsize(m) < MIN_RTCP_XR_PACKET_SIZE) {
290 			ortp_warning("Too short RTCP XR packet.");
291 			return FALSE;
292 		}
293 		return TRUE;
294 	}
295 	return FALSE;
296 }
297 
rtcp_XR_get_block_type(const mblk_t * m)298 rtcp_xr_block_type_t rtcp_XR_get_block_type(const mblk_t *m) {
299 	rtcp_xr_generic_block_header_t *bh = (rtcp_xr_generic_block_header_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
300 	return bh->bt;
301 }
302 
rtcp_XR_get_ssrc(const mblk_t * m)303 uint32_t rtcp_XR_get_ssrc(const mblk_t *m) {
304 	rtcp_xr_header_t *xh = (rtcp_xr_header_t *)m->b_rptr;
305 	return ntohl(xh->ssrc);
306 }
307 
rtcp_XR_rcvr_rtt_get_ntp_timestamp(const mblk_t * m)308 uint64_t rtcp_XR_rcvr_rtt_get_ntp_timestamp(const mblk_t *m) {
309 	uint64_t ts = 0;
310 	rtcp_xr_rcvr_rtt_report_block_t *b = (rtcp_xr_rcvr_rtt_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
311 	ts = ntohl(b->ntp_timestamp_msw);
312 	ts <<= 32;
313 	ts |= ntohl(b->ntp_timestamp_lsw);
314 	return ts;
315 }
316 
rtcp_XR_dlrr_get_ssrc(const mblk_t * m)317 uint32_t rtcp_XR_dlrr_get_ssrc(const mblk_t *m) {
318 	rtcp_xr_dlrr_report_subblock_t *b = (rtcp_xr_dlrr_report_subblock_t *)(m->b_rptr + sizeof(rtcp_xr_header_t) + sizeof(rtcp_xr_generic_block_header_t));
319 	return ntohl(b->ssrc);
320 }
321 
rtcp_XR_dlrr_get_lrr(const mblk_t * m)322 uint32_t rtcp_XR_dlrr_get_lrr(const mblk_t *m) {
323 	rtcp_xr_dlrr_report_subblock_t *b = (rtcp_xr_dlrr_report_subblock_t *)(m->b_rptr + sizeof(rtcp_xr_header_t) + sizeof(rtcp_xr_generic_block_header_t));
324 	return ntohl(b->lrr);
325 }
326 
rtcp_XR_dlrr_get_dlrr(const mblk_t * m)327 uint32_t rtcp_XR_dlrr_get_dlrr(const mblk_t *m) {
328 	rtcp_xr_dlrr_report_subblock_t *b = (rtcp_xr_dlrr_report_subblock_t *)(m->b_rptr + sizeof(rtcp_xr_header_t) + sizeof(rtcp_xr_generic_block_header_t));
329 	return ntohl(b->dlrr);
330 }
331 
rtcp_XR_stat_summary_get_flags(const mblk_t * m)332 uint8_t rtcp_XR_stat_summary_get_flags(const mblk_t *m) {
333 	rtcp_xr_generic_block_header_t *bh = (rtcp_xr_generic_block_header_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
334 	return bh->flags;
335 }
336 
rtcp_XR_stat_summary_get_ssrc(const mblk_t * m)337 uint32_t rtcp_XR_stat_summary_get_ssrc(const mblk_t *m) {
338 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
339 	return ntohl(b->ssrc);
340 }
341 
rtcp_XR_stat_summary_get_begin_seq(const mblk_t * m)342 uint16_t rtcp_XR_stat_summary_get_begin_seq(const mblk_t *m) {
343 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
344 	return ntohs(b->begin_seq);
345 }
346 
rtcp_XR_stat_summary_get_end_seq(const mblk_t * m)347 uint16_t rtcp_XR_stat_summary_get_end_seq(const mblk_t *m) {
348 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
349 	return ntohs(b->end_seq);
350 }
351 
rtcp_XR_stat_summary_get_lost_packets(const mblk_t * m)352 uint32_t rtcp_XR_stat_summary_get_lost_packets(const mblk_t *m) {
353 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
354 	return ntohl(b->lost_packets);
355 }
356 
rtcp_XR_stat_summary_get_dup_packets(const mblk_t * m)357 uint32_t rtcp_XR_stat_summary_get_dup_packets(const mblk_t *m) {
358 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
359 	return ntohl(b->dup_packets);
360 }
361 
rtcp_XR_stat_summary_get_min_jitter(const mblk_t * m)362 uint32_t rtcp_XR_stat_summary_get_min_jitter(const mblk_t *m) {
363 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
364 	return ntohl(b->min_jitter);
365 }
366 
rtcp_XR_stat_summary_get_max_jitter(const mblk_t * m)367 uint32_t rtcp_XR_stat_summary_get_max_jitter(const mblk_t *m) {
368 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
369 	return ntohl(b->max_jitter);
370 }
371 
rtcp_XR_stat_summary_get_mean_jitter(const mblk_t * m)372 uint32_t rtcp_XR_stat_summary_get_mean_jitter(const mblk_t *m) {
373 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
374 	return ntohl(b->mean_jitter);
375 }
376 
rtcp_XR_stat_summary_get_dev_jitter(const mblk_t * m)377 uint32_t rtcp_XR_stat_summary_get_dev_jitter(const mblk_t *m) {
378 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
379 	return ntohl(b->dev_jitter);
380 }
381 
rtcp_XR_stat_summary_get_min_ttl_or_hl(const mblk_t * m)382 uint8_t rtcp_XR_stat_summary_get_min_ttl_or_hl(const mblk_t *m) {
383 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
384 	return b->min_ttl_or_hl;
385 }
386 
rtcp_XR_stat_summary_get_max_ttl_or_hl(const mblk_t * m)387 uint8_t rtcp_XR_stat_summary_get_max_ttl_or_hl(const mblk_t *m) {
388 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
389 	return b->max_ttl_or_hl;
390 }
391 
rtcp_XR_stat_summary_get_mean_ttl_or_hl(const mblk_t * m)392 uint8_t rtcp_XR_stat_summary_get_mean_ttl_or_hl(const mblk_t *m) {
393 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
394 	return b->mean_ttl_or_hl;
395 }
396 
rtcp_XR_stat_summary_get_dev_ttl_or_hl(const mblk_t * m)397 uint8_t rtcp_XR_stat_summary_get_dev_ttl_or_hl(const mblk_t *m) {
398 	rtcp_xr_stat_summary_report_block_t *b = (rtcp_xr_stat_summary_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
399 	return b->dev_ttl_or_hl;
400 }
401 
rtcp_XR_voip_metrics_get_ssrc(const mblk_t * m)402 uint32_t rtcp_XR_voip_metrics_get_ssrc(const mblk_t *m) {
403 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
404 	return ntohl(b->ssrc);
405 }
406 
rtcp_XR_voip_metrics_get_loss_rate(const mblk_t * m)407 uint8_t rtcp_XR_voip_metrics_get_loss_rate(const mblk_t *m) {
408 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
409 	return b->loss_rate;
410 }
411 
rtcp_XR_voip_metrics_get_discard_rate(const mblk_t * m)412 uint8_t rtcp_XR_voip_metrics_get_discard_rate(const mblk_t *m) {
413 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
414 	return b->discard_rate;
415 }
416 
rtcp_XR_voip_metrics_get_burst_density(const mblk_t * m)417 uint8_t rtcp_XR_voip_metrics_get_burst_density(const mblk_t *m) {
418 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
419 	return b->burst_density;
420 }
421 
rtcp_XR_voip_metrics_get_gap_density(const mblk_t * m)422 uint8_t rtcp_XR_voip_metrics_get_gap_density(const mblk_t *m) {
423 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
424 	return b->gap_density;
425 }
426 
rtcp_XR_voip_metrics_get_burst_duration(const mblk_t * m)427 uint16_t rtcp_XR_voip_metrics_get_burst_duration(const mblk_t *m) {
428 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
429 	return ntohs(b->burst_duration);
430 }
431 
rtcp_XR_voip_metrics_get_gap_duration(const mblk_t * m)432 uint16_t rtcp_XR_voip_metrics_get_gap_duration(const mblk_t *m) {
433 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
434 	return ntohs(b->gap_duration);
435 }
436 
rtcp_XR_voip_metrics_get_round_trip_delay(const mblk_t * m)437 uint16_t rtcp_XR_voip_metrics_get_round_trip_delay(const mblk_t *m) {
438 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
439 	return ntohs(b->round_trip_delay);
440 }
441 
rtcp_XR_voip_metrics_get_end_system_delay(const mblk_t * m)442 uint16_t rtcp_XR_voip_metrics_get_end_system_delay(const mblk_t *m) {
443 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
444 	return ntohs(b->end_system_delay);
445 }
446 
rtcp_XR_voip_metrics_get_signal_level(const mblk_t * m)447 uint8_t rtcp_XR_voip_metrics_get_signal_level(const mblk_t *m) {
448 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
449 	return b->signal_level;
450 }
451 
rtcp_XR_voip_metrics_get_noise_level(const mblk_t * m)452 uint8_t rtcp_XR_voip_metrics_get_noise_level(const mblk_t *m) {
453 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
454 	return b->noise_level;
455 }
456 
rtcp_XR_voip_metrics_get_rerl(const mblk_t * m)457 uint8_t rtcp_XR_voip_metrics_get_rerl(const mblk_t *m) {
458 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
459 	return b->rerl;
460 }
461 
rtcp_XR_voip_metrics_get_gmin(const mblk_t * m)462 uint8_t rtcp_XR_voip_metrics_get_gmin(const mblk_t *m) {
463 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
464 	return b->gmin;
465 }
466 
rtcp_XR_voip_metrics_get_r_factor(const mblk_t * m)467 uint8_t rtcp_XR_voip_metrics_get_r_factor(const mblk_t *m) {
468 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
469 	return b->r_factor;
470 }
471 
rtcp_XR_voip_metrics_get_ext_r_factor(const mblk_t * m)472 uint8_t rtcp_XR_voip_metrics_get_ext_r_factor(const mblk_t *m) {
473 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
474 	return b->ext_r_factor;
475 }
476 
rtcp_XR_voip_metrics_get_mos_lq(const mblk_t * m)477 uint8_t rtcp_XR_voip_metrics_get_mos_lq(const mblk_t *m) {
478 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
479 	return b->mos_lq;
480 }
481 
rtcp_XR_voip_metrics_get_mos_cq(const mblk_t * m)482 uint8_t rtcp_XR_voip_metrics_get_mos_cq(const mblk_t *m) {
483 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
484 	return b->mos_cq;
485 }
486 
rtcp_XR_voip_metrics_get_rx_config(const mblk_t * m)487 uint8_t rtcp_XR_voip_metrics_get_rx_config(const mblk_t *m) {
488 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
489 	return b->rx_config;
490 }
491 
rtcp_XR_voip_metrics_get_jb_nominal(const mblk_t * m)492 uint16_t rtcp_XR_voip_metrics_get_jb_nominal(const mblk_t *m) {
493 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
494 	return ntohs(b->jb_nominal);
495 }
496 
rtcp_XR_voip_metrics_get_jb_maximum(const mblk_t * m)497 uint16_t rtcp_XR_voip_metrics_get_jb_maximum(const mblk_t *m) {
498 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
499 	return ntohs(b->jb_maximum);
500 }
501 
rtcp_XR_voip_metrics_get_jb_abs_max(const mblk_t * m)502 uint16_t rtcp_XR_voip_metrics_get_jb_abs_max(const mblk_t *m) {
503 	rtcp_xr_voip_metrics_report_block_t *b = (rtcp_xr_voip_metrics_report_block_t *)(m->b_rptr + sizeof(rtcp_xr_header_t));
504 	return ntohs(b->jb_abs_max);
505 }
506 
507 
508 /* RTCP RTPFB accessors */
rtcp_is_RTPFB(const mblk_t * m)509 bool_t rtcp_is_RTPFB(const mblk_t *m) {
510 	const rtcp_common_header_t *ch = rtcp_get_common_header(m);
511 	if ((ch != NULL) && (rtcp_common_header_get_packet_type(ch) == RTCP_RTPFB)) {
512 		if (msgdsize(m) < MIN_RTCP_RTPFB_PACKET_SIZE) {
513 			ortp_warning("Too short RTCP RTPFB packet.");
514 			return FALSE;
515 		}
516 		return TRUE;
517 	}
518 	return FALSE;
519 }
520 
521 /* Same as rtcp_is_RTPFB but not needing msgpullup. To be used internally only. */
rtcp_is_RTPFB_internal(const mblk_t * m)522 bool_t rtcp_is_RTPFB_internal(const mblk_t *m) {
523 	rtcp_common_header_t *ch = (rtcp_common_header_t *)m->b_rptr;
524 	return (rtcp_common_header_get_packet_type(ch) == RTCP_RTPFB) ? TRUE : FALSE;
525 }
526 
rtcp_RTPFB_get_type(const mblk_t * m)527 rtcp_rtpfb_type_t rtcp_RTPFB_get_type(const mblk_t *m) {
528 	rtcp_common_header_t *ch = (rtcp_common_header_t *)m->b_rptr;
529 	return (rtcp_rtpfb_type_t)rtcp_common_header_get_rc(ch);
530 }
531 
rtcp_RTPFB_get_packet_sender_ssrc(const mblk_t * m)532 uint32_t rtcp_RTPFB_get_packet_sender_ssrc(const mblk_t *m) {
533 	rtcp_fb_header_t *fbh = (rtcp_fb_header_t *)(m->b_rptr + sizeof(rtcp_common_header_t));
534 	return ntohl(fbh->packet_sender_ssrc);
535 }
536 
rtcp_RTPFB_get_media_source_ssrc(const mblk_t * m)537 uint32_t rtcp_RTPFB_get_media_source_ssrc(const mblk_t *m) {
538 	rtcp_fb_header_t *fbh = (rtcp_fb_header_t *)(m->b_rptr + sizeof(rtcp_common_header_t));
539 	return ntohl(fbh->media_source_ssrc);
540 }
541 
rtcp_RTPFB_generic_nack_get_fci(const mblk_t * m)542 rtcp_fb_generic_nack_fci_t * rtcp_RTPFB_generic_nack_get_fci(const mblk_t *m) {
543 	size_t size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + sizeof(rtcp_fb_generic_nack_fci_t);
544 	size_t rtcp_size = rtcp_get_size(m);
545 	if (size > rtcp_size) {
546 		return NULL;
547 	}
548 	return (rtcp_fb_generic_nack_fci_t *)(m->b_rptr + size - sizeof(rtcp_fb_generic_nack_fci_t));
549 }
550 
rtcp_RTPFB_tmmbr_get_fci(const mblk_t * m)551 rtcp_fb_tmmbr_fci_t * rtcp_RTPFB_tmmbr_get_fci(const mblk_t *m) {
552 	size_t size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + sizeof(rtcp_fb_tmmbr_fci_t);
553 	size_t rtcp_size = rtcp_get_size(m);
554 	if (size > rtcp_size) {
555 		return NULL;
556 	}
557 	return (rtcp_fb_tmmbr_fci_t *)(m->b_rptr + size - sizeof(rtcp_fb_tmmbr_fci_t));
558 }
559 
rtcp_RTPFB_tmmbr_get_max_bitrate(const mblk_t * m)560 uint64_t rtcp_RTPFB_tmmbr_get_max_bitrate(const mblk_t *m) {
561 	rtcp_fb_tmmbr_fci_t *fci = rtcp_RTPFB_tmmbr_get_fci(m);
562 	return rtcp_fb_tmmbr_fci_get_mxtbr_mantissa(fci) * (1 << rtcp_fb_tmmbr_fci_get_mxtbr_exp(fci));
563 }
564 
565 
566 /* RTCP PSFB accessors */
rtcp_is_PSFB(const mblk_t * m)567 bool_t rtcp_is_PSFB(const mblk_t *m) {
568 	const rtcp_common_header_t *ch = rtcp_get_common_header(m);
569 	if ((ch != NULL) && (rtcp_common_header_get_packet_type(ch) == RTCP_PSFB)) {
570 		if (msgdsize(m) < MIN_RTCP_PSFB_PACKET_SIZE) {
571 			ortp_warning("Too short RTCP PSFB packet.");
572 			return FALSE;
573 		}
574 		return TRUE;
575 	}
576 	return FALSE;
577 }
578 
579 /* Same as rtcp_is_PSFB but not needing msgpullup. To be used internally only. */
rtcp_is_PSFB_internal(const mblk_t * m)580 bool_t rtcp_is_PSFB_internal(const mblk_t *m) {
581 	rtcp_common_header_t *ch = (rtcp_common_header_t *)m->b_rptr;
582 	return (rtcp_common_header_get_packet_type(ch) == RTCP_PSFB) ? TRUE : FALSE;
583 }
584 
rtcp_PSFB_get_type(const mblk_t * m)585 rtcp_psfb_type_t rtcp_PSFB_get_type(const mblk_t *m) {
586 	rtcp_common_header_t *ch = (rtcp_common_header_t *)m->b_rptr;
587 	return (rtcp_psfb_type_t)rtcp_common_header_get_rc(ch);
588 }
589 
rtcp_PSFB_get_packet_sender_ssrc(const mblk_t * m)590 uint32_t rtcp_PSFB_get_packet_sender_ssrc(const mblk_t *m) {
591 	rtcp_fb_header_t *fbh = (rtcp_fb_header_t *)(m->b_rptr + sizeof(rtcp_common_header_t));
592 	return ntohl(fbh->packet_sender_ssrc);
593 }
594 
rtcp_PSFB_get_media_source_ssrc(const mblk_t * m)595 uint32_t rtcp_PSFB_get_media_source_ssrc(const mblk_t *m) {
596 	rtcp_fb_header_t *fbh = (rtcp_fb_header_t *)(m->b_rptr + sizeof(rtcp_common_header_t));
597 	return ntohl(fbh->media_source_ssrc);
598 }
599 
rtcp_PSFB_fir_get_fci(const mblk_t * m,unsigned int idx)600 rtcp_fb_fir_fci_t * rtcp_PSFB_fir_get_fci(const mblk_t *m, unsigned int idx) {
601 	size_t size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + ((idx + 1) * sizeof(rtcp_fb_fir_fci_t));
602 	size_t rtcp_size = rtcp_get_size(m);
603 	if (size > rtcp_size) {
604 		return NULL;
605 	}
606 	return (rtcp_fb_fir_fci_t *)(m->b_rptr + size - sizeof(rtcp_fb_fir_fci_t));
607 }
608 
rtcp_PSFB_sli_get_fci(const mblk_t * m,unsigned int idx)609 rtcp_fb_sli_fci_t * rtcp_PSFB_sli_get_fci(const mblk_t *m, unsigned int idx) {
610 	size_t size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + ((idx + 1) * sizeof(rtcp_fb_sli_fci_t));
611 	size_t rtcp_size = rtcp_get_size(m);
612 	if (size > rtcp_size) {
613 		return NULL;
614 	}
615 	return (rtcp_fb_sli_fci_t *)(m->b_rptr + size - sizeof(rtcp_fb_sli_fci_t));
616 }
617 
rtcp_PSFB_rpsi_get_fci(const mblk_t * m)618 rtcp_fb_rpsi_fci_t * rtcp_PSFB_rpsi_get_fci(const mblk_t *m) {
619 	return (rtcp_fb_rpsi_fci_t *)(m->b_rptr + sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t));
620 }
621 
rtcp_PSFB_rpsi_get_fci_bit_string_len(const mblk_t * m)622 uint16_t rtcp_PSFB_rpsi_get_fci_bit_string_len(const mblk_t *m) {
623 	rtcp_fb_rpsi_fci_t *fci = rtcp_PSFB_rpsi_get_fci(m);
624 	uint16_t bit_string_len_in_bytes = (uint16_t)(rtcp_get_size(m) - (sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + 2));
625 	return ((bit_string_len_in_bytes * 8) - fci->pb);
626 }
627