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 <math.h>
22 
23 #include "ortp/ortp.h"
24 #include "ortp/rtpsession.h"
25 #include "ortp/rtcp.h"
26 #include "rtpsession_priv.h"
27 #include "utils.h"
28 
29 
calc_rate(double d1,double d2)30 static uint8_t calc_rate(double d1, double d2) {
31 	double rate = (d1 / d2) * 256;
32 	uint32_t int_rate = (uint32_t)rate;
33 	if (int_rate > 255) int_rate = 255;
34 	return (uint8_t)int_rate;
35 }
36 
rtcp_xr_header_init(uint8_t * buf,RtpSession * session,int bytes_len)37 static int rtcp_xr_header_init(uint8_t *buf, RtpSession *session, int bytes_len) {
38 	rtcp_xr_header_t *header = (rtcp_xr_header_t *)buf;
39 	rtcp_common_header_init(&header->ch, session, RTCP_XR, 0, bytes_len);
40 	header->ssrc = htonl(session->snd.ssrc);
41 	return sizeof(rtcp_xr_header_t);
42 }
43 
rtcp_xr_rcvr_rtt_init(uint8_t * buf,RtpSession * session)44 static int rtcp_xr_rcvr_rtt_init(uint8_t *buf, RtpSession *session) {
45 	struct timeval tv;
46 	uint64_t ntp;
47 	rtcp_xr_rcvr_rtt_report_block_t *block = (rtcp_xr_rcvr_rtt_report_block_t *)buf;
48 
49 	block->bh.bt = RTCP_XR_RCVR_RTT;
50 	block->bh.flags = 0; // Reserved bits
51 	block->bh.length = htons(2);
52 	ortp_gettimeofday(&tv, NULL);
53 	ntp = ortp_timeval_to_ntp(&tv);
54 	block->ntp_timestamp_msw = htonl(ntp >> 32);
55 	block->ntp_timestamp_lsw = htonl(ntp & 0xFFFFFFFF);
56 	return sizeof(rtcp_xr_rcvr_rtt_report_block_t);
57 }
58 
rtcp_xr_dlrr_init(uint8_t * buf,RtpSession * session)59 static int rtcp_xr_dlrr_init(uint8_t *buf, RtpSession *session) {
60 	uint32_t dlrr = 0;
61 	rtcp_xr_dlrr_report_block_t *block = (rtcp_xr_dlrr_report_block_t *)buf;
62 
63 	block->bh.bt = RTCP_XR_DLRR;
64 	block->bh.flags = 0; // Reserved bits
65 	block->bh.length = htons(3);
66 	block->content[0].ssrc = htonl(rtp_session_get_recv_ssrc(session));
67 	block->content[0].lrr = htonl(session->rtcp_xr_stats.last_rcvr_rtt_ts);
68 	if (session->rtcp_xr_stats.last_rcvr_rtt_time.tv_sec != 0) {
69 		struct timeval now;
70 		double delay;
71 		ortp_gettimeofday(&now, NULL);
72 		delay = ((now.tv_sec - session->rtcp_xr_stats.last_rcvr_rtt_time.tv_sec)
73 			+ ((now.tv_usec - session->rtcp_xr_stats.last_rcvr_rtt_time.tv_usec) * 1e-6)) * 65536;
74 		dlrr = (uint32_t) delay;
75 	}
76 	block->content[0].dlrr = htonl(dlrr);
77 	return sizeof(rtcp_xr_dlrr_report_block_t);
78 }
79 
rtcp_xr_stat_summary_init(uint8_t * buf,RtpSession * session)80 static int rtcp_xr_stat_summary_init(uint8_t *buf, RtpSession *session) {
81 	rtcp_xr_stat_summary_report_block_t *block = (rtcp_xr_stat_summary_report_block_t *)buf;
82 	uint16_t last_rcv_seq = session->rtp.hwrcv_extseq & 0xFFFF;
83 	uint8_t flags = session->rtcp.xr_conf.stat_summary_flags;
84 	uint32_t expected_packets;
85 	uint32_t lost_packets = 0;
86 	uint32_t dup_packets = session->rtcp_xr_stats.dup_since_last_stat_summary;
87 
88 	/* Compute lost and duplicate packets statistics */
89 	if (flags & OrtpRtcpXrStatSummaryLoss) {
90 		uint32_t no_duplicate_received = session->rtcp_xr_stats.rcv_since_last_stat_summary - dup_packets;
91 		expected_packets = last_rcv_seq - session->rtcp_xr_stats.rcv_seq_at_last_stat_summary;
92 		lost_packets = (expected_packets > session->rtcp_xr_stats.rcv_since_last_stat_summary)
93 			? (expected_packets - no_duplicate_received) : 0;
94 	}
95 
96 	block->bh.bt = RTCP_XR_STAT_SUMMARY;
97 	block->bh.flags = flags;
98 	block->bh.length = htons(9);
99 	block->ssrc = htonl(rtp_session_get_recv_ssrc(session));
100 	block->begin_seq = htons(session->rtcp_xr_stats.rcv_seq_at_last_stat_summary + 1);
101 	block->end_seq = htons(last_rcv_seq + 1);
102 	block->lost_packets = htonl(lost_packets);
103 	block->dup_packets = htonl(dup_packets);
104 	if ((flags & OrtpRtcpXrStatSummaryJitt)
105 		&& (session->rtcp_xr_stats.rcv_since_last_stat_summary > 0)) {
106 		block->min_jitter = htonl(session->rtcp_xr_stats.min_jitter_since_last_stat_summary);
107 		block->max_jitter = htonl(session->rtcp_xr_stats.max_jitter_since_last_stat_summary);
108 		block->mean_jitter = htonl((session->rtcp_xr_stats.rcv_since_last_stat_summary > 1)
109 			? (uint32_t)session->rtcp_xr_stats.newm_jitter_since_last_stat_summary : 0);
110 		block->dev_jitter = htonl((session->rtcp_xr_stats.rcv_since_last_stat_summary > 2)
111 			? (uint32_t)sqrt(session->rtcp_xr_stats.news_jitter_since_last_stat_summary / (session->rtcp_xr_stats.rcv_since_last_stat_summary - 2)) : 0);
112 	} else {
113 		block->min_jitter = htonl(0);
114 		block->max_jitter = htonl(0);
115 		block->mean_jitter = htonl(0);
116 		block->dev_jitter = htonl(0);
117 	}
118 	if ((flags & (OrtpRtcpXrStatSummaryTTL | OrtpRtcpXrStatSummaryHL))
119 		&& (session->rtcp_xr_stats.rcv_since_last_stat_summary > 0)) {
120 		block->min_ttl_or_hl = session->rtcp_xr_stats.min_ttl_or_hl_since_last_stat_summary;
121 		block->max_ttl_or_hl = session->rtcp_xr_stats.max_ttl_or_hl_since_last_stat_summary;
122 		block->mean_ttl_or_hl = (session->rtcp_xr_stats.rcv_since_last_stat_summary > 0)
123 			? (uint8_t)session->rtcp_xr_stats.newm_ttl_or_hl_since_last_stat_summary : 0;
124 		block->dev_ttl_or_hl = (session->rtcp_xr_stats.rcv_since_last_stat_summary > 1)
125 			? (uint8_t)sqrt(session->rtcp_xr_stats.news_ttl_or_hl_since_last_stat_summary / (session->rtcp_xr_stats.rcv_since_last_stat_summary - 1)) : 0;
126 	} else {
127 		block->min_ttl_or_hl = 0;
128 		block->max_ttl_or_hl = 0;
129 		block->mean_ttl_or_hl = 0;
130 		block->dev_ttl_or_hl = 0;
131 	}
132 
133 	session->rtcp_xr_stats.rcv_seq_at_last_stat_summary = last_rcv_seq;
134 	session->rtcp_xr_stats.rcv_since_last_stat_summary = 0;
135 	session->rtcp_xr_stats.dup_since_last_stat_summary = 0;
136 
137 	return sizeof(rtcp_xr_stat_summary_report_block_t);
138 }
139 
rtcp_xr_voip_metrics_init(uint8_t * buf,RtpSession * session)140 static int rtcp_xr_voip_metrics_init(uint8_t *buf, RtpSession *session) {
141 	JBParameters jbparams;
142 	uint32_t expected_packets;
143 	uint32_t lost_packets;
144 	rtcp_xr_voip_metrics_report_block_t *block = (rtcp_xr_voip_metrics_report_block_t *)buf;
145 	float rtt = rtp_session_get_round_trip_propagation(session);
146 	uint16_t int_rtt = (uint16_t)((rtt >= 0) ? (rtt * 1000) : 0);
147 	float qi = -1;
148 	float lq_qi = -1;
149 
150 	rtp_session_get_jitter_buffer_params(session, &jbparams);
151 	if (session->rtcp.xr_media_callbacks.average_qi != NULL) {
152 		qi = session->rtcp.xr_media_callbacks.average_qi(session->rtcp.xr_media_callbacks.userdata);
153 	}
154 	if (session->rtcp.xr_media_callbacks.average_lq_qi != NULL) {
155 		lq_qi = session->rtcp.xr_media_callbacks.average_lq_qi(session->rtcp.xr_media_callbacks.userdata);
156 	}
157 
158 	block->bh.bt = RTCP_XR_VOIP_METRICS;
159 	block->bh.flags = 0; // Reserved bits
160 	block->bh.length = htons(8);
161 	block->ssrc = htonl(rtp_session_get_recv_ssrc(session));
162 	block->gmin = RTCP_XR_GMIN;
163 	block->reserved2 = 0;
164 
165 	// Fill RX config
166 	block->rx_config = 0;
167 	if (jbparams.adaptive) {
168 		block->rx_config |= RTCP_XR_VOIP_METRICS_CONFIG_JBA_ADA;
169 	} else {
170 		block->rx_config |= RTCP_XR_VOIP_METRICS_CONFIG_JBA_NON;
171 	}
172 	if (session->rtcp.xr_media_callbacks.plc != NULL) {
173 		switch (session->rtcp.xr_media_callbacks.plc(session->rtcp.xr_media_callbacks.userdata)) {
174 			default:
175 			case OrtpRtcpXrNoPlc:
176 				block->rx_config |= RTCP_XR_VOIP_METRICS_CONFIG_PLC_UNS;
177 				break;
178 			case OrtpRtcpXrSilencePlc:
179 				block->rx_config |= RTCP_XR_VOIP_METRICS_CONFIG_PLC_DIS;
180 				break;
181 			case OrtpRtcpXrEnhancedPlc:
182 				block->rx_config |= RTCP_XR_VOIP_METRICS_CONFIG_PLC_ENH;
183 				break;
184 		}
185 	} else {
186 		block->rx_config |= RTCP_XR_VOIP_METRICS_CONFIG_PLC_UNS;
187 	}
188 
189 	// Fill JB fields
190 	block->jb_nominal = htons((uint16_t)jbparams.nom_size);
191 	if (jbparams.adaptive) {
192 		block->jb_maximum = htons((session->rtp.jittctl.adapt_jitt_comp_ts * 1000) / session->rtp.jittctl.clock_rate);
193 	} else {
194 		block->jb_maximum = block->jb_nominal;
195 	}
196 	block->jb_abs_max = htons(65535);
197 
198 	if (session->rtcp_xr_stats.rcv_count > 0) {
199 		expected_packets = session->rtcp_xr_stats.last_rcv_seq - session->rtcp_xr_stats.first_rcv_seq + 1;
200 		lost_packets = expected_packets - session->rtcp_xr_stats.rcv_count;
201 		block->loss_rate = calc_rate((double)lost_packets, (double)expected_packets);
202 		block->discard_rate = calc_rate((double)session->rtcp_xr_stats.discarded_count, (double)expected_packets);
203 		// TODO: fill burst_density, gap_density, burst_duration, gap_duration
204 		block->burst_density = 0;
205 		block->gap_density = 0;
206 		block->burst_duration = htons(0);
207 		block->gap_duration = htons(0);
208 		block->round_trip_delay = htons(int_rtt);
209 		// TODO: fill end_system_delay
210 		block->end_system_delay = htons(0);
211 		if (session->rtcp.xr_media_callbacks.signal_level != NULL) {
212 			block->signal_level = session->rtcp.xr_media_callbacks.signal_level(session->rtcp.xr_media_callbacks.userdata);
213 		} else {
214 			block->signal_level = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
215 		}
216 		if (session->rtcp.xr_media_callbacks.noise_level != NULL) {
217 			block->noise_level = session->rtcp.xr_media_callbacks.noise_level(session->rtcp.xr_media_callbacks.userdata);
218 		} else {
219 			block->noise_level = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
220 		}
221 		block->rerl = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
222 		if (qi < 0) {
223 			block->r_factor = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
224 		} else {
225 			block->r_factor = (uint8_t)(qi * 20);
226 		}
227 		block->ext_r_factor = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
228 		if (lq_qi < 0) {
229 			block->mos_lq = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
230 		} else {
231 			block->mos_lq = (uint8_t)(lq_qi * 10);
232 			if (block->mos_lq < 10) block->mos_lq = 10;
233 		}
234 		if (qi < 0) {
235 			block->mos_cq = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
236 		} else {
237 			block->mos_cq = (uint8_t)(qi * 10);
238 			if (block->mos_cq < 10) block->mos_cq = 10;
239 		}
240 	} else {
241 		block->loss_rate = 0;
242 		block->discard_rate = 0;
243 		block->burst_density = 0;
244 		block->gap_density = 0;
245 		block->burst_duration = htons(0);
246 		block->gap_duration = htons(0);
247 		block->round_trip_delay = htons(0);
248 		block->end_system_delay = htons(0);
249 		block->signal_level = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
250 		block->noise_level = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
251 		block->rerl = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
252 		block->r_factor = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
253 		block->ext_r_factor = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
254 		block->mos_lq = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
255 		block->mos_cq = ORTP_RTCP_XR_UNAVAILABLE_PARAMETER;
256 	}
257 	return sizeof(rtcp_xr_voip_metrics_report_block_t);
258 }
259 
260 
make_xr_rcvr_rtt(RtpSession * session)261 mblk_t * make_xr_rcvr_rtt(RtpSession *session) {
262 	int size = sizeof(rtcp_xr_header_t) + sizeof(rtcp_xr_rcvr_rtt_report_block_t);
263 	mblk_t *h = allocb(size, 0);
264 	h->b_wptr += rtcp_xr_header_init(h->b_wptr, session, size);
265 	h->b_wptr += rtcp_xr_rcvr_rtt_init(h->b_wptr, session);
266 	return h;
267 }
268 
make_xr_dlrr(RtpSession * session)269 mblk_t * make_xr_dlrr(RtpSession *session) {
270 	int size = sizeof(rtcp_xr_header_t) + sizeof(rtcp_xr_dlrr_report_block_t);
271 	mblk_t *h = allocb(size, 0);
272 	h->b_wptr += rtcp_xr_header_init(h->b_wptr, session, size);
273 	h->b_wptr += rtcp_xr_dlrr_init(h->b_wptr, session);
274 	return h;
275 }
276 
make_xr_stat_summary(RtpSession * session)277 mblk_t * make_xr_stat_summary(RtpSession *session) {
278 	int size = sizeof(rtcp_xr_header_t) + sizeof(rtcp_xr_stat_summary_report_block_t);
279 	mblk_t *h = allocb(size, 0);
280 	h->b_wptr += rtcp_xr_header_init(h->b_wptr, session, size);
281 	h->b_wptr += rtcp_xr_stat_summary_init(h->b_wptr, session);
282 	return h;
283 }
284 
make_xr_voip_metrics(RtpSession * session)285 mblk_t * make_xr_voip_metrics(RtpSession *session) {
286 	int size = sizeof(rtcp_xr_header_t) + sizeof(rtcp_xr_voip_metrics_report_block_t);
287 	mblk_t *h = allocb(size, 0);
288 	h->b_wptr += rtcp_xr_header_init(h->b_wptr, session, size);
289 	h->b_wptr += rtcp_xr_voip_metrics_init(h->b_wptr, session);
290 	return h;
291 }
292 
rtp_session_configure_rtcp_xr(RtpSession * session,const OrtpRtcpXrConfiguration * config)293 void rtp_session_configure_rtcp_xr(RtpSession *session, const OrtpRtcpXrConfiguration *config) {
294 	if (config != NULL) {
295 		session->rtcp.xr_conf = *config;
296 	}
297 }
298 
rtp_session_set_rtcp_xr_media_callbacks(RtpSession * session,const OrtpRtcpXrMediaCallbacks * cbs)299 void rtp_session_set_rtcp_xr_media_callbacks(RtpSession *session, const OrtpRtcpXrMediaCallbacks *cbs) {
300 	if (cbs != NULL) {
301 		memcpy(&session->rtcp.xr_media_callbacks, cbs, sizeof(session->rtcp.xr_media_callbacks));
302 	} else {
303 		memset(&session->rtcp.xr_media_callbacks, 0, sizeof(session->rtcp.xr_media_callbacks));
304 	}
305 }
306