FreeCalypso > hg > rtp-debug-utils
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 } |