blob: 7b9be68183ca205bd6df6fc892e67a6456392328 [file] [log] [blame]
Harald Welte067d66e2017-12-13 17:24:03 +01001module RTP_Emulation {
2
3/* Functionalities that we want this module to imeplement:
4 * * act as a RTP source that generates a RTP Stream
5 * * act asaa RTP sink that consumes a RTP Stream
6 *
7 * for all of the above, we want to be able to
8 * * specify the payload type
9 * * specify the interval / sample rate
10 * * create drop-outs in the stream
11 * * detect reordered or lost frames
12 * * validate if the size of the frames matches epectations
13 * * play back real audio (at least some tones?)
14 * * enable/disable generation/verification of RTCP
15 */
16
Harald Weltea4ca4462018-02-09 00:17:14 +010017/* Ideas:
18
19* each component consists of transmitter and receiver
20* transmitters and receivers can be operated as tuple?
21* high-level operation
22** set-up config at transmitter + receiver
23** transmit sequence of payloads
24** verify receiption of those payloads
25* can operate full-duplex/bi-directional as needed
26
27* transmitter
28** trigger transmission of n number of packets
29** transmit them at normal ptime interval
30** payload size configurable
31** payload contents PRBS or the like
32
33* receiver
34** count number of related packets at receiver
35** check received payload type
36** check received timestamp increments
37** check received seq_nr increments
38** (optionally) check for SSRC
39** (optionally) check for payload size
40** (optionally) check for payload contents
41
42* later
43** how to test transcoding?
44** how to test pure play-out endpoints (rx only)?
45** how to test "Rx from wrong IP/port" scenarios?
46** how to test RTCP?
47** maybe keep ports un-connected to show wrong src -lrt
48
49*/
50
51
52
53
Harald Welte067d66e2017-12-13 17:24:03 +010054import from General_Types all;
55import from Osmocom_Types all;
56import from IPL4asp_Types all;
57import from RTP_Types all;
58import from RTP_CodecPort all;
59import from RTP_CodecPort_CtrlFunct all;
60
Harald Welte80981642017-12-24 23:59:47 +010061import from IuUP_Types all;
62import from IuUP_Emulation all;
63
Harald Welte067d66e2017-12-13 17:24:03 +010064type component RTP_Emulation_CT {
65 /* down-facing ports for RTP and RTCP codec ports on top of IPL4asp */
66 port RTP_CODEC_PT RTP;
67 var integer g_rtp_conn_id := -1;
68 port RTP_CODEC_PT RTCP;
69 var integer g_rtcp_conn_id := -1;
70
71 /* user-facing port for controlling the binding */
72 port RTPEM_CTRL_PT CTRL;
73
74 /* configurable by user, should be fixed */
Harald Welte80981642017-12-24 23:59:47 +010075 var RtpemConfig g_cfg := c_RtpemDefaultCfg;
Harald Welte067d66e2017-12-13 17:24:03 +010076
Harald Weltecb8b4272018-03-28 19:57:58 +020077 /* statistics */
78 var RtpemStats g_stats_rtp := c_RtpemStatsReset;
79 var RtpemStats g_stats_rtcp := c_RtpemStatsReset;
80
Harald Welte067d66e2017-12-13 17:24:03 +010081 var HostName g_remote_host;
82 var PortNumber g_remote_port;
83 var HostName g_local_host;
84 var PortNumber g_local_port;
85
86 /* state variables, change over time */
87 var boolean g_rx_enabled := false;
Pau Espin Pedrole38bfe02019-05-17 18:40:43 +020088 var boolean g_tx_connected := false; /* Set to true after connect() */
Harald Welte067d66e2017-12-13 17:24:03 +010089 var LIN2_BO_LAST g_tx_next_seq := 0;
90 var uint32_t g_tx_next_ts := 0;
91
92 var INT7b g_rx_payload_type := 0;
93 var LIN2_BO_LAST g_rx_last_seq;
94 var uint32_t g_rx_last_ts;
Harald Welte80981642017-12-24 23:59:47 +010095
96 var IuUP_Entity g_iuup_ent; // := valueof(t_IuUP_Entity(1));
Harald Welte067d66e2017-12-13 17:24:03 +010097}
98
99type enumerated RtpemMode {
100 RTPEM_MODE_NONE,
101 RTPEM_MODE_TXONLY,
102 RTPEM_MODE_RXONLY,
103 RTPEM_MODE_BIDIR
104};
105
Harald Weltecb8b4272018-03-28 19:57:58 +0200106type record RtpemStats {
107 /* number of packets transmitted */
108 integer num_pkts_tx,
109 /* number of RTP payload bytes transmitted */
110 integer bytes_payload_tx,
111
112 /* number of packets received */
113 integer num_pkts_rx,
114 /* number of RTP payload bytes received */
115 integer bytes_payload_rx,
116 /* number of packets received out-of-sequence */
117 integer num_pkts_rx_err_seq,
118 /* number of packets received wrong timestamp */
119 integer num_pkts_rx_err_ts,
Philipp Maierc290d722018-07-24 18:51:36 +0200120 /* number of packets received wrong payload type */
121 integer num_pkts_rx_err_pt,
Harald Weltecb8b4272018-03-28 19:57:58 +0200122 /* number of packets received during Rx disable */
Philipp Maiera071ee42019-02-21 16:17:32 +0100123 integer num_pkts_rx_err_disabled,
124 /* number of packets received with mismatching payload */
125 integer num_pkts_rx_err_payload
Harald Weltecb8b4272018-03-28 19:57:58 +0200126}
127
128const RtpemStats c_RtpemStatsReset := {
129 num_pkts_tx := 0,
130 bytes_payload_tx := 0,
131 num_pkts_rx := 0,
132 bytes_payload_rx := 0,
133 num_pkts_rx_err_seq := 0,
134 num_pkts_rx_err_ts := 0,
Philipp Maierc290d722018-07-24 18:51:36 +0200135 num_pkts_rx_err_pt := 0,
Philipp Maiera071ee42019-02-21 16:17:32 +0100136 num_pkts_rx_err_disabled := 0,
137 num_pkts_rx_err_payload := 0
Harald Weltecb8b4272018-03-28 19:57:58 +0200138}
139
Harald Welte3f6f48f2017-12-24 21:48:33 +0100140type record RtpemConfig {
141 INT7b tx_payload_type,
142 integer tx_samplerate_hz,
143 integer tx_duration_ms,
144 BIT32_BO_LAST tx_ssrc,
Harald Welte80981642017-12-24 23:59:47 +0100145 octetstring tx_fixed_payload optional,
Philipp Maiera071ee42019-02-21 16:17:32 +0100146 octetstring rx_fixed_payload optional,
Harald Welte80981642017-12-24 23:59:47 +0100147 boolean iuup_mode,
148 boolean iuup_tx_init
Harald Welte3f6f48f2017-12-24 21:48:33 +0100149};
150
Harald Welte80981642017-12-24 23:59:47 +0100151const RtpemConfig c_RtpemDefaultCfg := {
Harald Welte3f6f48f2017-12-24 21:48:33 +0100152 tx_payload_type := 0,
153 tx_samplerate_hz := 8000,
154 tx_duration_ms := 20,
155 tx_ssrc := '11011110101011011011111011101111'B,
Harald Welte80981642017-12-24 23:59:47 +0100156 tx_fixed_payload := '01020304'O,
Philipp Maiera071ee42019-02-21 16:17:32 +0100157 rx_fixed_payload := '01020304'O,
Harald Welte80981642017-12-24 23:59:47 +0100158 iuup_mode := false,
159 iuup_tx_init := true
Harald Welte3f6f48f2017-12-24 21:48:33 +0100160}
161
Harald Welte067d66e2017-12-13 17:24:03 +0100162signature RTPEM_bind(in HostName local_host, inout PortNumber local_port);
163signature RTPEM_connect(in HostName remote_host, in PortNumber remote_port);
164signature RTPEM_mode(in RtpemMode mode);
Harald Welte3f6f48f2017-12-24 21:48:33 +0100165signature RTPEM_configure(in RtpemConfig cfg);
Harald Weltecb8b4272018-03-28 19:57:58 +0200166signature RTPEM_stats_get(out RtpemStats stats, in boolean rtcp);
Harald Welte067d66e2017-12-13 17:24:03 +0100167
168type port RTPEM_CTRL_PT procedure {
Harald Weltecb8b4272018-03-28 19:57:58 +0200169 inout RTPEM_bind, RTPEM_connect, RTPEM_mode, RTPEM_configure, RTPEM_stats_get;
Harald Welte067d66e2017-12-13 17:24:03 +0100170} with { extension "internal" };
171
Harald Welte1af40332018-03-29 08:50:33 +0200172function f_rtpem_bind(RTPEM_CTRL_PT pt, in HostName local_host, inout PortNumber local_port) {
173 pt.call(RTPEM_bind:{local_host, local_port}) {
174 [] pt.getreply(RTPEM_bind:{local_host, ?}) -> param (local_port) {};
175 }
176}
177function f_rtpem_connect(RTPEM_CTRL_PT pt, in HostName remote_host, in PortNumber remote_port) {
178 pt.call(RTPEM_connect:{remote_host, remote_port}) {
179 [] pt.getreply(RTPEM_connect:{remote_host, remote_port}) {};
180 }
181}
182function f_rtpem_mode(RTPEM_CTRL_PT pt, in RtpemMode mode) {
183 pt.call(RTPEM_mode:{mode}) {
184 [] pt.getreply(RTPEM_mode:{mode}) {};
185 }
186}
187function f_rtpem_configure(RTPEM_CTRL_PT pt, in RtpemConfig cfg) {
188 pt.call(RTPEM_configure:{cfg}) {
189 [] pt.getreply(RTPEM_configure:{cfg}) {};
190 }
191}
192function f_rtpem_stats_get(RTPEM_CTRL_PT pt, boolean rtcp := false) return RtpemStats {
193 var RtpemStats stats;
194 pt.call(RTPEM_stats_get:{-, rtcp}) {
195 [] pt.getreply(RTPEM_stats_get:{?, rtcp}) -> param(stats) {};
196 }
197 return stats;
198}
199
Philipp Maier2321ef92018-06-27 17:52:04 +0200200function f_rtpem_stats_compare_value(integer a, integer b, integer tolerance := 0) return boolean {
201 var integer temp;
Harald Welte5c49ba42018-03-29 08:51:20 +0200202
Philipp Maier2321ef92018-06-27 17:52:04 +0200203 temp := (a - b)
204 if (temp < 0) {
205 temp := -temp;
206 }
207
208 if (temp > tolerance) {
Harald Welte5c49ba42018-03-29 08:51:20 +0200209 return false;
210 }
Philipp Maier2321ef92018-06-27 17:52:04 +0200211
Harald Welte5c49ba42018-03-29 08:51:20 +0200212 return true;
213}
Harald Welte1af40332018-03-29 08:50:33 +0200214
Philipp Maier2321ef92018-06-27 17:52:04 +0200215/* Cross-compare two rtpem-statistics. The transmission statistics on the a side
216 * must match the reception statistics on the other side and vice versa. The
217 * user may also supply a tolerance value (number of packets) when deviations
218 * are acceptable */
219function f_rtpem_stats_compare(RtpemStats a, RtpemStats b, integer tolerance := 0) return boolean {
220 var integer plen;
221
222 log("stats A: ", a);
223 log("stats B: ", b);
224 log("tolerance: ", tolerance, " packets");
225
226 if (f_rtpem_stats_compare_value(a.num_pkts_tx, b.num_pkts_rx, tolerance) == false) {
227 return false;
228 }
229
230 if (f_rtpem_stats_compare_value(a.num_pkts_rx, b.num_pkts_tx, tolerance) == false) {
231 return false;
232 }
233
234 if(a.num_pkts_tx > 0) {
235 plen := a.bytes_payload_tx / a.num_pkts_tx;
236 } else {
237 plen := 0;
238 }
239
240 if (f_rtpem_stats_compare_value(a.bytes_payload_tx, b.bytes_payload_rx, tolerance * plen) == false) {
241 return false;
242 }
243
244 if (f_rtpem_stats_compare_value(a.bytes_payload_rx, b.bytes_payload_tx, tolerance * plen) == false) {
245 return false;
246 }
247
248 return true;
249}
Harald Welte1af40332018-03-29 08:50:33 +0200250
Philipp Maier36291392018-07-25 09:40:44 +0200251/* Check the statistics for general signs of errors. This is a basic general
252 * check that will fit most situations and is intended to be executed by
253 * the testcases as as needed. */
254function f_rtpem_stats_err_check(RtpemStats s) {
255 log("stats: ", s);
256
257 /* Check if there was some activity at either on the RX or on the
258 * TX side, but complete silence would indicate some problem */
259 if (s.num_pkts_tx < 1 and s.num_pkts_rx < 1) {
260 setverdict(fail, "no RTP packet activity detected (packets)");
261 mtc.stop;
262 }
263 if (s.bytes_payload_tx < 1 and s.bytes_payload_rx < 1) {
264 setverdict(fail, "no RTP packet activity detected (bytes)");
265 mtc.stop;
266 }
267
268 /* Check error counters */
269 if (s.num_pkts_rx_err_seq != 0) {
270 setverdict(fail, "RTP packet sequence number errors occurred");
271 mtc.stop;
272 }
273 if (s.num_pkts_rx_err_ts != 0) {
274 setverdict(fail, "RTP packet timestamp errors occurred");
275 mtc.stop;
276 }
277 if (s.num_pkts_rx_err_pt != 0) {
278 setverdict(fail, "RTP packet payload type errors occurred");
279 mtc.stop;
280 }
281 if (s.num_pkts_rx_err_disabled != 0) {
282 setverdict(fail, "RTP packets received while RX was disabled");
283 mtc.stop;
284 }
Philipp Maiera071ee42019-02-21 16:17:32 +0100285 if (s.num_pkts_rx_err_payload != 0) {
286 setverdict(fail, "RTP packets with mismatching payload received");
287 mtc.stop;
288 }
Philipp Maier36291392018-07-25 09:40:44 +0200289}
290
Harald Welte067d66e2017-12-13 17:24:03 +0100291template PDU_RTP ts_RTP(BIT32_BO_LAST ssrc, INT7b pt, LIN2_BO_LAST seq, uint32_t ts,
292 octetstring payload, BIT1 marker := '0'B) := {
293 version := 2,
294 padding_ind := '0'B,
295 extension_ind := '0'B,
296 CSRC_count := 0,
297 marker_bit := marker,
298 payload_type := pt,
299 sequence_number := seq,
Harald Welte8a4d3952017-12-24 21:30:23 +0100300 time_stamp := int2bit(ts, 32),
Harald Welte067d66e2017-12-13 17:24:03 +0100301 SSRC_id := ssrc,
302 CSRCs := omit,
303 ext_header := omit,
304 data := payload
305}
306
307private function f_tx_rtp(octetstring payload, BIT1 marker := '0'B) runs on RTP_Emulation_CT {
Harald Welte80981642017-12-24 23:59:47 +0100308 if (g_cfg.iuup_mode) {
309 payload := f_IuUP_Em_tx_encap(g_iuup_ent, payload);
310 }
Harald Welte3f6f48f2017-12-24 21:48:33 +0100311 var PDU_RTP rtp := valueof(ts_RTP(g_cfg.tx_ssrc, g_cfg.tx_payload_type, g_tx_next_seq,
Harald Welte067d66e2017-12-13 17:24:03 +0100312 g_tx_next_ts, payload, marker));
313 RTP.send(t_RTP_Send(g_rtp_conn_id, RTP_messages_union:{rtp:=rtp}));
314 /* increment sequence + timestamp for next transmit */
315 g_tx_next_seq := g_tx_next_seq + 1;
Harald Welte3f6f48f2017-12-24 21:48:33 +0100316 g_tx_next_ts := g_tx_next_ts + (g_cfg.tx_samplerate_hz / (1000 / g_cfg.tx_duration_ms));
Harald Welte067d66e2017-12-13 17:24:03 +0100317}
318
319function f_main() runs on RTP_Emulation_CT
320{
321 var Result res;
Harald Weltecb8b4272018-03-28 19:57:58 +0200322 var boolean is_rtcp
Harald Welte067d66e2017-12-13 17:24:03 +0100323
Harald Welte3f6f48f2017-12-24 21:48:33 +0100324 timer T_transmit := int2float(g_cfg.tx_duration_ms)/1000.0;
Harald Welte067d66e2017-12-13 17:24:03 +0100325 var RTP_RecvFrom rx_rtp;
Harald Welte3f6f48f2017-12-24 21:48:33 +0100326 var RtpemConfig cfg;
Harald Welte067d66e2017-12-13 17:24:03 +0100327 var template RTP_RecvFrom tr := {
328 connId := ?,
329 remName := ?,
330 remPort := ?,
331 locName := ?,
332 locPort := ?,
333 msg := ?
334 };
335 var template RTP_RecvFrom tr_rtp := tr;
336 var template RTP_RecvFrom tr_rtcp := tr;
Harald Welte067d66e2017-12-13 17:24:03 +0100337 tr_rtp.msg := { rtp := ? };
Harald Welte067d66e2017-12-13 17:24:03 +0100338 tr_rtcp.msg := { rtcp := ? };
339
Harald Welte80981642017-12-24 23:59:47 +0100340 g_iuup_ent := valueof(t_IuUP_Entity(g_cfg.iuup_tx_init));
341
Harald Welte067d66e2017-12-13 17:24:03 +0100342 while (true) {
343 alt {
344 /* control procedures (calls) from the user */
345 [] CTRL.getcall(RTPEM_bind:{?,?}) -> param(g_local_host, g_local_port) {
346 if (g_local_port rem 2 == 1) {
347 //CTRL.raise(RTPEM_bind, "Local Port is not an even port number!");
348 log("Local Port is not an even port number!");
349 continue;
350 }
Pau Espin Pedrole38bfe02019-05-17 18:40:43 +0200351
352 g_tx_connected := false; /* will set it back to true upon next connect() call */
Harald Welte067d66e2017-12-13 17:24:03 +0100353 res := RTP_CodecPort_CtrlFunct.f_IPL4_listen(RTP, g_local_host,
354 g_local_port, {udp:={}});
Harald Welte9220f632018-05-23 20:27:02 +0200355 if (not ispresent(res.connId)) {
356 setverdict(fail, "Could not listen on RTP socket, check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200357 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200358 }
Harald Welte067d66e2017-12-13 17:24:03 +0100359 g_rtp_conn_id := res.connId;
Harald Welte9774e7a2018-03-29 08:49:38 +0200360 tr_rtp.connId := g_rtp_conn_id;
Harald Welte98eb1bf2018-04-02 18:18:44 +0200361 res := RTP_CodecPort_CtrlFunct.f_IPL4_listen(RTCP, g_local_host,
Harald Welte067d66e2017-12-13 17:24:03 +0100362 g_local_port+1, {udp:={}});
Harald Welte9220f632018-05-23 20:27:02 +0200363 if (not ispresent(res.connId)) {
364 setverdict(fail, "Could not listen on RTCP socket, check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200365 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200366 }
Harald Welte067d66e2017-12-13 17:24:03 +0100367 g_rtcp_conn_id := res.connId;
Harald Welte9774e7a2018-03-29 08:49:38 +0200368 tr_rtcp.connId := g_rtcp_conn_id;
Harald Welte067d66e2017-12-13 17:24:03 +0100369 CTRL.reply(RTPEM_bind:{g_local_host, g_local_port});
370 }
371 [] CTRL.getcall(RTPEM_connect:{?,?}) -> param (g_remote_host, g_remote_port) {
372 if (g_remote_port rem 2 == 1) {
373 //CTRL.raise(RTPEM_connect, "Remote Port is not an even number!");
374 log("Remote Port is not an even number!");
375 continue;
376 }
377 res := RTP_CodecPort_CtrlFunct.f_IPL4_connect(RTP, g_remote_host,
378 g_remote_port,
379 g_local_host, g_local_port,
380 g_rtp_conn_id, {udp:={}});
Harald Welte9220f632018-05-23 20:27:02 +0200381 if (not ispresent(res.connId)) {
382 setverdict(fail, "Could not connect to RTP socket, check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200383 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200384 }
Harald Welte067d66e2017-12-13 17:24:03 +0100385 res := RTP_CodecPort_CtrlFunct.f_IPL4_connect(RTCP, g_remote_host,
386 g_remote_port+1,
387 g_local_host, g_local_port+1,
388 g_rtcp_conn_id, {udp:={}});
Harald Welte9220f632018-05-23 20:27:02 +0200389 if (not ispresent(res.connId)) {
390 setverdict(fail, "Could not connect to RTCP socket, check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200391 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200392 }
Pau Espin Pedrole38bfe02019-05-17 18:40:43 +0200393 g_tx_connected := true;
Harald Welte067d66e2017-12-13 17:24:03 +0100394 CTRL.reply(RTPEM_connect:{g_remote_host, g_remote_port});
395 }
396 [] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_NONE}) {
397 T_transmit.stop;
398 g_rx_enabled := false;
Harald Welte80981642017-12-24 23:59:47 +0100399 CTRL.reply(RTPEM_mode:{RTPEM_MODE_NONE});
Harald Welte067d66e2017-12-13 17:24:03 +0100400 }
401 [] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_TXONLY}) {
402 /* start transmit timer */
403 T_transmit.start;
404 g_rx_enabled := false;
Harald Welte80981642017-12-24 23:59:47 +0100405 CTRL.reply(RTPEM_mode:{RTPEM_MODE_TXONLY});
Harald Welte067d66e2017-12-13 17:24:03 +0100406 }
407 [] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_RXONLY}) {
408
409 T_transmit.stop;
410 if (g_rx_enabled == false) {
411 /* flush queues */
412 RTP.clear;
413 RTCP.clear;
414 g_rx_enabled := true;
415 }
Harald Welte80981642017-12-24 23:59:47 +0100416 CTRL.reply(RTPEM_mode:{RTPEM_MODE_RXONLY});
Harald Welte067d66e2017-12-13 17:24:03 +0100417 }
418 [] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_BIDIR}) {
419 T_transmit.start;
420 if (g_rx_enabled == false) {
421 /* flush queues */
422 RTP.clear;
423 RTCP.clear;
424 g_rx_enabled := true;
425 }
Harald Welte80981642017-12-24 23:59:47 +0100426 CTRL.reply(RTPEM_mode:{RTPEM_MODE_BIDIR});
Harald Welte067d66e2017-12-13 17:24:03 +0100427 }
Harald Welte3f6f48f2017-12-24 21:48:33 +0100428 [] CTRL.getcall(RTPEM_configure:{?}) -> param (cfg) {
429 g_cfg := cfg;
Harald Welte80981642017-12-24 23:59:47 +0100430 g_iuup_ent.cfg.active_init := g_cfg.iuup_tx_init;
431 CTRL.reply(RTPEM_configure:{cfg});
Harald Welte3f6f48f2017-12-24 21:48:33 +0100432 }
Harald Weltecb8b4272018-03-28 19:57:58 +0200433 [] CTRL.getcall(RTPEM_stats_get:{?, ?}) -> param (is_rtcp) {
434 if (is_rtcp) {
435 CTRL.reply(RTPEM_stats_get:{g_stats_rtcp, is_rtcp});
436 } else {
437 CTRL.reply(RTPEM_stats_get:{g_stats_rtp, is_rtcp});
438 }
439 }
Harald Welte067d66e2017-12-13 17:24:03 +0100440
Harald Weltecb8b4272018-03-28 19:57:58 +0200441
442
443 /* simply ignore any RTTP/RTP if receiver not enabled */
444 [g_rx_enabled==false] RTP.receive(tr_rtp) {
445 g_stats_rtp.num_pkts_rx_err_disabled := g_stats_rtp.num_pkts_rx_err_disabled+1;
446 }
Harald Welte98eb1bf2018-04-02 18:18:44 +0200447 [g_rx_enabled==false] RTCP.receive(tr_rtcp) {
Harald Weltecb8b4272018-03-28 19:57:58 +0200448 g_stats_rtcp.num_pkts_rx_err_disabled := g_stats_rtcp.num_pkts_rx_err_disabled+1;
449 }
Harald Welte067d66e2017-12-13 17:24:03 +0100450
451 /* process received RTCP/RTP if receiver enabled */
452 [g_rx_enabled] RTP.receive(tr_rtp) -> value rx_rtp {
Harald Weltecb8b4272018-03-28 19:57:58 +0200453 /* increment counters */
Philipp Maierc290d722018-07-24 18:51:36 +0200454 if (rx_rtp.msg.rtp.payload_type != g_cfg.tx_payload_type) {
455 g_stats_rtp.num_pkts_rx_err_pt := g_stats_rtp.num_pkts_rx_err_pt+1;
456 }
Harald Weltecb8b4272018-03-28 19:57:58 +0200457 g_stats_rtp.num_pkts_rx := g_stats_rtp.num_pkts_rx+1;
458 g_stats_rtp.bytes_payload_rx := g_stats_rtp.bytes_payload_rx +
459 lengthof(rx_rtp.msg.rtp.data);
Philipp Maiera071ee42019-02-21 16:17:32 +0100460 if (ispresent(g_cfg.rx_fixed_payload) and rx_rtp.msg.rtp.data != g_cfg.rx_fixed_payload) {
461 g_stats_rtp.num_pkts_rx_err_payload := g_stats_rtp.num_pkts_rx_err_payload + 1;
462 }
Harald Welte80981642017-12-24 23:59:47 +0100463 if (g_cfg.iuup_mode) {
464 rx_rtp.msg.rtp.data := f_IuUP_Em_rx_decaps(g_iuup_ent, rx_rtp.msg.rtp.data);
465 }
Harald Welte067d66e2017-12-13 17:24:03 +0100466 }
467 [g_rx_enabled] RTCP.receive(tr_rtcp) -> value rx_rtp {
Harald Welte8d3ea0e2018-03-29 08:50:18 +0200468 //log("RX RTCP: ", rx_rtp);
Harald Weltecb8b4272018-03-28 19:57:58 +0200469 g_stats_rtcp.num_pkts_rx := g_stats_rtcp.num_pkts_rx+1;
Harald Welte067d66e2017-12-13 17:24:03 +0100470 }
471
472 /* transmit if timer has expired */
Pau Espin Pedrole38bfe02019-05-17 18:40:43 +0200473 [g_tx_connected] T_transmit.timeout {
Harald Welte067d66e2017-12-13 17:24:03 +0100474 /* send one RTP frame, re-start timer */
Harald Welte3f6f48f2017-12-24 21:48:33 +0100475 f_tx_rtp(g_cfg.tx_fixed_payload);
Harald Welte067d66e2017-12-13 17:24:03 +0100476 T_transmit.start;
Harald Weltecb8b4272018-03-28 19:57:58 +0200477 /* update counters */
478 g_stats_rtp.num_pkts_tx := g_stats_rtp.num_pkts_tx+1;
479 g_stats_rtp.bytes_payload_tx := g_stats_rtp.bytes_payload_tx +
480 lengthof(g_cfg.tx_fixed_payload);
Harald Welte067d66e2017-12-13 17:24:03 +0100481 }
482
483 /* fail on any unexpected messages */
484 [] RTP.receive {
485 setverdict(fail, "Received unexpected type from RTP");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200486 mtc.stop;
Harald Welte067d66e2017-12-13 17:24:03 +0100487 }
488 [] RTCP.receive {
489 setverdict(fail, "Received unexpected type from RTCP");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200490 mtc.stop;
Harald Welte067d66e2017-12-13 17:24:03 +0100491 }
492 }
493 }
494}
495
496
497}