comparison net-traffic/rtp-stream-gen.c @ 10:e686bc92c7d8

revamp for new subdir structure and configure script
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 15 May 2024 01:44:46 +0000
parents rtp-stream-gen.c@d180987db615
children
comparison
equal deleted inserted replaced
9:c00510e1ae8b 10:e686bc92c7d8
1 /*
2 * This program generates a dummy RTP stream, sending RTP packets with
3 * a dummy payload to the specified destination IP:port, paced in time
4 * every 20 ms. The purpose is to test the behaviour of affordably-available
5 * Internet connections when presented with such traffic: the intent is
6 * to capture this packet stream on the receiving end with tcpdump and then
7 * analyze the pcap for problem signs of packet loss, jitter and reordering.
8 */
9
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <sys/time.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <stdio.h>
16 #include <stdint.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <strings.h>
20 #include <unistd.h>
21
22 #define RTP_PACKET_HDR_SIZE 12
23 #define RTP_MAX_PAYLOAD 160
24 #define GSM_FR_BYTES 33
25
26 struct rtp_packet {
27 uint8_t v_p_x_cc;
28 uint8_t m_pt;
29 uint16_t seq;
30 uint32_t tstamp;
31 uint32_t ssrc;
32 uint8_t payload[RTP_MAX_PAYLOAD];
33 };
34
35 static const uint8_t gsmfr_silence_frame[GSM_FR_BYTES] = {
36 0xDA, 0xA7, 0xAA, 0xA5, 0x1A,
37 0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
38 0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
39 0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
40 0x50, 0x20, 0x38, 0xE4, 0x6D, 0xB9, 0x1B,
41 };
42
43 static struct sockaddr_in sin_src, sin_dest;
44 static struct rtp_packet rtp_pkt;
45 static unsigned rtp_pkt_len, req_packet_count;
46 static int udp_fd;
47
48 static void
49 parse_ip_port(arg, sin)
50 char *arg;
51 struct sockaddr_in *sin;
52 {
53 char *cp;
54 int rc;
55
56 cp = index(arg, ':');
57 if (!cp) {
58 fprintf(stderr, "error: missing ':' in IP:port argument\n");
59 exit(1);
60 }
61 *cp++ = '\0';
62 sin->sin_family = AF_INET;
63 rc = inet_aton(arg, &sin->sin_addr);
64 if (!rc) {
65 fprintf(stderr, "error: invalid IP address argument\n");
66 exit(1);
67 }
68 sin->sin_port = htons(atoi(cp));
69 }
70
71 static void
72 prepare_rtp_payload(type_arg)
73 char *type_arg;
74 {
75 unsigned pl_len;
76
77 if (!strcmp(type_arg, "pcmu")) {
78 rtp_pkt.m_pt = 0;
79 memset(rtp_pkt.payload, 0xFF, RTP_MAX_PAYLOAD);
80 pl_len = RTP_MAX_PAYLOAD;
81 } else if (!strcmp(type_arg, "pcma")) {
82 rtp_pkt.m_pt = 8;
83 memset(rtp_pkt.payload, 0xD5, RTP_MAX_PAYLOAD);
84 pl_len = RTP_MAX_PAYLOAD;
85 } else if (!strcmp(type_arg, "gsm")) {
86 rtp_pkt.m_pt = 3;
87 memcpy(rtp_pkt.payload, gsmfr_silence_frame, GSM_FR_BYTES);
88 pl_len = GSM_FR_BYTES;
89 } else {
90 fprintf(stderr, "error: invalid PL type argument \"%s\"\n",
91 type_arg);
92 exit(1);
93 }
94 rtp_pkt_len = RTP_PACKET_HDR_SIZE + pl_len;
95 }
96
97 static void
98 assign_rtpout_ssrc()
99 {
100 struct timeval curtime;
101
102 gettimeofday(&curtime, 0);
103 rtp_pkt.ssrc = curtime.tv_sec ^ curtime.tv_usec ^ getpid();
104 }
105
106 static void
107 prepare_udp_socket()
108 {
109 int rc;
110
111 udp_fd = socket(AF_INET, SOCK_DGRAM, 0);
112 if (udp_fd < 0) {
113 perror("socket(AF_INET, SOCK_DGRAM, 0)");
114 exit(1);
115 }
116 rc = bind(udp_fd, (struct sockaddr *) &sin_src, sizeof sin_src);
117 if (rc < 0) {
118 perror("bind");
119 exit(1);
120 }
121 rc = connect(udp_fd, (struct sockaddr *) &sin_dest, sizeof sin_dest);
122 if (rc < 0) {
123 perror("connect");
124 exit(1);
125 }
126 }
127
128 static void
129 send_out_packets()
130 {
131 unsigned n, seq, ts;
132
133 seq = 0;
134 ts = 0;
135 for (n = 0; n < req_packet_count; n++) {
136 rtp_pkt.seq = htons(seq);
137 rtp_pkt.tstamp = htonl(ts);
138 send(udp_fd, &rtp_pkt, rtp_pkt_len, 0);
139 seq++;
140 ts += 160;
141 usleep(20000);
142 }
143 }
144
145 main(argc, argv)
146 char **argv;
147 {
148 if (argc != 5) {
149 fprintf(stderr, "usage: %s src-IP:port dest-IP:port type num\n",
150 argv[0]);
151 exit(1);
152 }
153 parse_ip_port(argv[1], &sin_src);
154 parse_ip_port(argv[2], &sin_dest);
155 prepare_rtp_payload(argv[3]);
156 rtp_pkt.v_p_x_cc = 0x80;
157 assign_rtpout_ssrc();
158 req_packet_count = atoi(argv[4]);
159 prepare_udp_socket();
160 send_out_packets();
161 exit(0);
162 }