blob: c73aa5885b6f364d58e4b07d642c8de6672cdea2 [file] [log] [blame]
Harald Weltef07c2862017-11-18 17:16:24 +01001module RTP_Endpoint {
2
3 import from General_Types all;
4 import from Osmocom_Types all;
5 import from IPL4asp_Types all;
6 import from RTP_Types all;
7 import from RTP_CodecPort all;
8 import from RTP_CodecPort_CtrlFunct all;
9
10 /* state for one of the two UDP sockets in and endpoint */
11 type record RtpEndpointSub {
12 ConnectionId connection_id,
13 HostName local_name,
14 PortNumber local_port,
15 HostName remote_name,
16 PortNumber remote_port
17 }
18 /* state for one RTP+RTCP endpoint */
19 type record RtpEndpoint {
20 /* static configuration */
21 INT7b payload_type,
22 integer sample_rate, /* e.g. 8000 */
23 integer samples_per_pkt, /* e.g. 160 */
24 BIT32_BO_LAST ssrc,
25
26 /* dynamic state */
27 uint32_t next_ts,
28 LIN2_BO_LAST next_seq_no,
29 RtpEndpointSub rtp,
30 RtpEndpointSub rtcp
31 }
32
33/*
34 type component RTP_CT {
35 port RTP_CODEC_PT RTP;
36 ConnectionId g_conn_id := 1;
37 }
38
39 modulepar {
40 HostName rtp_local_ip := "127.0.0.1";
41 PortNumber rtp_local_base_port := 10000;
42 }
43*/
44
45 template RTP_messages_union ts_RTP(BIT1 marker, INT7b pt, LIN2_BO_LAST seq, uint32_t ts,
46 BIT32_BO_LAST ssrc, octetstring data) := {
47 rtp := {
48 version := 2,
49 padding_ind := '0'B,
50 extension_ind := '0'B,
51 CSRC_count := 0,
52 marker_bit := marker,
53 payload_type := pt,
54 sequence_number := seq,
55 time_stamp := int2bit(ts, 32),
56 SSRC_id := ssrc,
57 CSRCs := omit,
58 ext_header := omit,
59 data := data
60 }
61 }
62
63 template RTP_messages_union tr_RTP(template INT7b pt, template octetstring data,
64 template BIT32_BO_LAST ssrc := ?,
65 template LIN2_BO_LAST seq := ?,
66 template BIT32_BO_LAST ts := ?) := {
67 rtp := {
68 version := 2,
69 padding_ind := ?,
70 extension_ind := ?,
71 CSRC_count := ?,
72 marker_bit := ?,
73 payload_type := pt,
74 sequence_number := seq,
75 time_stamp := ts,
76 SSRC_id := ssrc,
77 CSRCs := *,
78 ext_header := *,
79 data := data
80 }
81 }
82
83 function rtp_endpoint_init(inout RtpEndpoint ep, charstring local_name, PortNumber local_port,
84 uint32_t ssrc) {
85 ep.rtp.local_name := local_name;
86 ep.rtp.local_port := local_port;
87 ep.rtp.connection_id := -1;
88 ep.rtcp.local_name := local_name;
89 ep.rtcp.local_port := local_port + 1;
90 ep.rtcp.connection_id := -1;
91 ep.ssrc := int2bit(ssrc, 32);
92
93 ep.payload_type := 99;
94 ep.sample_rate := 8000;
95 ep.samples_per_pkt := 160;
96 ep.next_ts := float2int(rnd()*4294967295.0);
97 ep.next_seq_no := float2int(rnd()*65535.0);
98 }
99
100 function rtp_endpoint_sub_close(inout RTP_CODEC_PT RTP, inout RtpEndpointSub sub) {
101 if (sub.connection_id != -1) {
102 f_IPL4_close(RTP, sub.connection_id, { udp := {} });
103 sub.connection_id := -1;
104 }
105 }
106
107 function rtp_endpoint_sub_connect(inout RTP_CODEC_PT RTP, inout RtpEndpointSub sub) {
108 var Result res;
109
110 res := f_IPL4_connect(RTP, sub.remote_name, sub.remote_port,
111 sub.local_name, sub.local_port, sub.connection_id, { udp := {} });
Harald Welte9220f632018-05-23 20:27:02 +0200112 if (not ispresent(res.connId)) {
113 setverdict(fail, "Could not connect RTP, check your configuration");
Daniel Willmannafce8662018-07-06 23:11:32 +0200114 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200115 }
Harald Weltef07c2862017-11-18 17:16:24 +0100116 /* connect without previous bind: save conenction id allocated by IPL4asp */
117 if (sub.connection_id == -1) {
118 sub.connection_id := res.connId;
119 }
120 }
121
122 function rtp_endpoint_close(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep) {
123 rtp_endpoint_sub_close(RTP, ep.rtp);
124 rtp_endpoint_sub_close(RTP, ep.rtcp);
125 }
126
127 /* connect the RTP and RTCP */
128 function rtp_endpoint_connect(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep) {
129 rtp_endpoint_sub_connect(RTP, ep.rtp);
130 rtp_endpoint_sub_connect(RTP, ep.rtcp);
131 }
132
133 function rtp_endpoint_sub_bind(inout RTP_CODEC_PT RTP, inout RtpEndpointSub sub) {
134 var Result res;
135 rtp_endpoint_sub_close(RTP, sub);
136 res := f_IPL4_listen(RTP, sub.local_name, sub.local_port, { udp := {} });
Harald Welte9220f632018-05-23 20:27:02 +0200137 if (not ispresent(res.connId)) {
138 setverdict(fail, "Could not listen to RTP, check your configuration");
Daniel Willmannafce8662018-07-06 23:11:32 +0200139 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200140 }
Harald Weltef07c2862017-11-18 17:16:24 +0100141 sub.connection_id := res.connId;
142 }
143
144 function rtp_endpoint_bind(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep) {
145 rtp_endpoint_sub_bind(RTP, ep.rtp);
146 rtp_endpoint_sub_bind(RTP, ep.rtcp);
147 }
148
149 /* send user-specified data through given endpoint, incrementing seq_no and timestamp */
150 function rtp_endpoint_send(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep,
151 octetstring data := '00'O) {
152 var RTP_messages_union rtp;
153 /* generate RTP packet as abstract TTCN-3 type */
154 rtp := valueof(ts_RTP('0'B, ep.payload_type, ep.next_seq_no, ep.next_ts, ep.ssrc, data));
155 /* increment for next packet */
156 ep.next_seq_no := ep.next_seq_no + 1;
157 ep.next_ts := ep.next_ts + ep.samples_per_pkt;
158 /* encode and send */
159 RTP.send(t_RTP_Send(ep.rtp.connection_id, rtp));
160 }
161}