162 lines
4.5 KiB
Plaintext
162 lines
4.5 KiB
Plaintext
module RTP_Endpoint {
|
|
|
|
import from General_Types all;
|
|
import from Osmocom_Types all;
|
|
import from IPL4asp_Types all;
|
|
import from RTP_Types all;
|
|
import from RTP_CodecPort all;
|
|
import from RTP_CodecPort_CtrlFunct all;
|
|
|
|
/* state for one of the two UDP sockets in and endpoint */
|
|
type record RtpEndpointSub {
|
|
ConnectionId connection_id,
|
|
HostName local_name,
|
|
PortNumber local_port,
|
|
HostName remote_name,
|
|
PortNumber remote_port
|
|
}
|
|
/* state for one RTP+RTCP endpoint */
|
|
type record RtpEndpoint {
|
|
/* static configuration */
|
|
INT7b payload_type,
|
|
integer sample_rate, /* e.g. 8000 */
|
|
integer samples_per_pkt, /* e.g. 160 */
|
|
BIT32_BO_LAST ssrc,
|
|
|
|
/* dynamic state */
|
|
uint32_t next_ts,
|
|
LIN2_BO_LAST next_seq_no,
|
|
RtpEndpointSub rtp,
|
|
RtpEndpointSub rtcp
|
|
}
|
|
|
|
/*
|
|
type component RTP_CT {
|
|
port RTP_CODEC_PT RTP;
|
|
ConnectionId g_conn_id := 1;
|
|
}
|
|
|
|
modulepar {
|
|
HostName rtp_local_ip := "127.0.0.1";
|
|
PortNumber rtp_local_base_port := 10000;
|
|
}
|
|
*/
|
|
|
|
template RTP_messages_union ts_RTP(BIT1 marker, INT7b pt, LIN2_BO_LAST seq, uint32_t ts,
|
|
BIT32_BO_LAST ssrc, octetstring data) := {
|
|
rtp := {
|
|
version := 2,
|
|
padding_ind := '0'B,
|
|
extension_ind := '0'B,
|
|
CSRC_count := 0,
|
|
marker_bit := marker,
|
|
payload_type := pt,
|
|
sequence_number := seq,
|
|
time_stamp := int2bit(ts, 32),
|
|
SSRC_id := ssrc,
|
|
CSRCs := omit,
|
|
ext_header := omit,
|
|
data := data
|
|
}
|
|
}
|
|
|
|
template RTP_messages_union tr_RTP(template INT7b pt, template octetstring data,
|
|
template BIT32_BO_LAST ssrc := ?,
|
|
template LIN2_BO_LAST seq := ?,
|
|
template BIT32_BO_LAST ts := ?) := {
|
|
rtp := {
|
|
version := 2,
|
|
padding_ind := ?,
|
|
extension_ind := ?,
|
|
CSRC_count := ?,
|
|
marker_bit := ?,
|
|
payload_type := pt,
|
|
sequence_number := seq,
|
|
time_stamp := ts,
|
|
SSRC_id := ssrc,
|
|
CSRCs := *,
|
|
ext_header := *,
|
|
data := data
|
|
}
|
|
}
|
|
|
|
function rtp_endpoint_init(inout RtpEndpoint ep, charstring local_name, PortNumber local_port,
|
|
uint32_t ssrc) {
|
|
ep.rtp.local_name := local_name;
|
|
ep.rtp.local_port := local_port;
|
|
ep.rtp.connection_id := -1;
|
|
ep.rtcp.local_name := local_name;
|
|
ep.rtcp.local_port := local_port + 1;
|
|
ep.rtcp.connection_id := -1;
|
|
ep.ssrc := int2bit(ssrc, 32);
|
|
|
|
ep.payload_type := 99;
|
|
ep.sample_rate := 8000;
|
|
ep.samples_per_pkt := 160;
|
|
ep.next_ts := float2int(rnd()*4294967295.0);
|
|
ep.next_seq_no := float2int(rnd()*65535.0);
|
|
}
|
|
|
|
function rtp_endpoint_sub_close(inout RTP_CODEC_PT RTP, inout RtpEndpointSub sub) {
|
|
if (sub.connection_id != -1) {
|
|
f_IPL4_close(RTP, sub.connection_id, { udp := {} });
|
|
sub.connection_id := -1;
|
|
}
|
|
}
|
|
|
|
function rtp_endpoint_sub_connect(inout RTP_CODEC_PT RTP, inout RtpEndpointSub sub) {
|
|
var Result res;
|
|
|
|
res := f_IPL4_connect(RTP, sub.remote_name, sub.remote_port,
|
|
sub.local_name, sub.local_port, sub.connection_id, { udp := {} });
|
|
if (not ispresent(res.connId)) {
|
|
setverdict(fail, "Could not connect RTP, check your configuration");
|
|
mtc.stop;
|
|
}
|
|
/* connect without previous bind: save conenction id allocated by IPL4asp */
|
|
if (sub.connection_id == -1) {
|
|
sub.connection_id := res.connId;
|
|
}
|
|
}
|
|
|
|
function rtp_endpoint_close(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep) {
|
|
rtp_endpoint_sub_close(RTP, ep.rtp);
|
|
rtp_endpoint_sub_close(RTP, ep.rtcp);
|
|
}
|
|
|
|
/* connect the RTP and RTCP */
|
|
function rtp_endpoint_connect(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep) {
|
|
rtp_endpoint_sub_connect(RTP, ep.rtp);
|
|
rtp_endpoint_sub_connect(RTP, ep.rtcp);
|
|
}
|
|
|
|
function rtp_endpoint_sub_bind(inout RTP_CODEC_PT RTP, inout RtpEndpointSub sub) {
|
|
var Result res;
|
|
rtp_endpoint_sub_close(RTP, sub);
|
|
res := f_IPL4_listen(RTP, sub.local_name, sub.local_port, { udp := {} });
|
|
if (not ispresent(res.connId)) {
|
|
setverdict(fail, "Could not listen to RTP, check your configuration");
|
|
mtc.stop;
|
|
}
|
|
sub.connection_id := res.connId;
|
|
}
|
|
|
|
function rtp_endpoint_bind(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep) {
|
|
rtp_endpoint_sub_bind(RTP, ep.rtp);
|
|
rtp_endpoint_sub_bind(RTP, ep.rtcp);
|
|
}
|
|
|
|
/* send user-specified data through given endpoint, incrementing seq_no and timestamp */
|
|
function rtp_endpoint_send(inout RTP_CODEC_PT RTP, inout RtpEndpoint ep,
|
|
octetstring data := '00'O) {
|
|
var RTP_messages_union rtp;
|
|
/* generate RTP packet as abstract TTCN-3 type */
|
|
rtp := valueof(ts_RTP('0'B, ep.payload_type, ep.next_seq_no, ep.next_ts, ep.ssrc, data));
|
|
/* increment for next packet */
|
|
ep.next_seq_no := ep.next_seq_no + 1;
|
|
ep.next_ts := ep.next_ts + ep.samples_per_pkt;
|
|
/* encode and send */
|
|
RTP.send(t_RTP_Send(ep.rtp.connection_id, rtp));
|
|
}
|
|
}
|