blob: d33423aa553e726eb532a73f52d18a60a3643a61 [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 := {} });
112 /* FIXME: Check for success (no res.errorCode) */
113
114 /* connect without previous bind: save conenction id allocated by IPL4asp */
115 if (sub.connection_id == -1) {
116 sub.connection_id := res.connId;
117 }
118 }
119
120 function rtp_endpoint_close(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep) {
121 rtp_endpoint_sub_close(RTP, ep.rtp);
122 rtp_endpoint_sub_close(RTP, ep.rtcp);
123 }
124
125 /* connect the RTP and RTCP */
126 function rtp_endpoint_connect(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep) {
127 rtp_endpoint_sub_connect(RTP, ep.rtp);
128 rtp_endpoint_sub_connect(RTP, ep.rtcp);
129 }
130
131 function rtp_endpoint_sub_bind(inout RTP_CODEC_PT RTP, inout RtpEndpointSub sub) {
132 var Result res;
133 rtp_endpoint_sub_close(RTP, sub);
134 res := f_IPL4_listen(RTP, sub.local_name, sub.local_port, { udp := {} });
135 /* FIXME: Check for success (no res.errorCode) */
136 sub.connection_id := res.connId;
137 }
138
139 function rtp_endpoint_bind(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep) {
140 rtp_endpoint_sub_bind(RTP, ep.rtp);
141 rtp_endpoint_sub_bind(RTP, ep.rtcp);
142 }
143
144 /* send user-specified data through given endpoint, incrementing seq_no and timestamp */
145 function rtp_endpoint_send(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep,
146 octetstring data := '00'O) {
147 var RTP_messages_union rtp;
148 /* generate RTP packet as abstract TTCN-3 type */
149 rtp := valueof(ts_RTP('0'B, ep.payload_type, ep.next_seq_no, ep.next_ts, ep.ssrc, data));
150 /* increment for next packet */
151 ep.next_seq_no := ep.next_seq_no + 1;
152 ep.next_ts := ep.next_ts + ep.samples_per_pkt;
153 /* encode and send */
154 RTP.send(t_RTP_Send(ep.rtp.connection_id, rtp));
155 }
156}