1 #include "tx_api.h"
2 #include "nx_api.h"
3 #include "netxtestcontrol.h"
4
5 extern void test_control_return(UINT);
6
7 #if !defined(NX_DISABLE_IPV4) && defined(__PRODUCT_NETXDUO__) && !defined(NX_DISABLE_PACKET_CHAIN)
8 #include "nx_rtp_sender.h"
9
10 #define DEMO_STACK_SIZE 4096
11
12 #define NUM_PACKETS 20
13 #define PACKET_SIZE 1536
14 #define PACKET_POOL_SIZE (NUM_PACKETS * (PACKET_SIZE + sizeof(NX_PACKET)))
15
16 #define DEMO_MULTICAST_IP_ADDRESS IP_ADDRESS(224, 1, 0, 55)
17
18 #define RTP_SERVER_ADDRESS IP_ADDRESS(1, 2, 3, 4)
19 #define RTP_CLIENT_1_ADDRESS IP_ADDRESS(1, 2, 3, 5)
20 #define RTP_CLIENT_2_ADDRESS IP_ADDRESS(1, 2, 3, 6)
21 #define RTP_CLIENT_RTP_PORT 6002
22 #define RTP_CLIENT_RTCP_PORT 6003
23 #define RTP_PAYLOAD_TYPE 96
24 #define CNAME "AzureRTOS@microsoft.com"
25
26 /* Define test data. */
27 #define TEST_TIMESTAMP 1234
28 #define TEST_MSW 123
29 #define TEST_LSW 456
30
31 /* Define the number of tests to do */
32 #define TEST_CYCLES 5
33
34 static UCHAR test_rtp_packet_data[] = "test rtp packet data";
35
36 /* Define the ThreadX object control blocks... */
37
38 static TX_THREAD ntest_0;
39 static TX_THREAD ntest_1;
40 static TX_THREAD ntest_2;
41
42 static NX_PACKET_POOL pool_0;
43 static NX_IP ip_0;
44 static NX_IP ip_1;
45 static NX_IP ip_2;
46 static NX_UDP_SOCKET rtp_client_1_socket;
47 static NX_UDP_SOCKET rtp_client_2_socket;
48
49 static TX_SEMAPHORE semaphore_test_1_done;
50 static TX_SEMAPHORE semaphore_test_2_done;
51
52 /* Define rtp sender control block. */
53 static NX_RTP_SENDER rtp_0;
54 static NX_RTP_SESSION rtp_session_0;
55 static UINT rtp_port;
56 static UINT rtcp_port;
57
58
59 /* Define thread prototypes. */
60
61 static void ntest_0_entry(ULONG thread_input);
62 static void ntest_1_entry(ULONG thread_input);
63 static void ntest_2_entry(ULONG thread_input);
64 extern void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
65 extern void test_control_return(UINT status);
66
67 #ifdef CTEST
test_application_define(void * first_unused_memory)68 VOID test_application_define(void *first_unused_memory)
69 #else
70 void netx_rtp_multicast_test_application_define(void *first_unused_memory)
71 #endif
72 {
73
74 CHAR *pointer;
75 UINT status;
76
77 /* Print out test information banner. */
78 printf("NetX Test: RTP Multicast Test............................................");
79
80 /* Setup the working pointer. */
81 pointer = (CHAR *)first_unused_memory;
82
83 /* Create the server thread. */
84 tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
85 pointer, DEMO_STACK_SIZE,
86 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
87
88 pointer = pointer + DEMO_STACK_SIZE;
89
90 /* Create the client thread. */
91 tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
92 pointer, DEMO_STACK_SIZE,
93 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
94
95 pointer = pointer + DEMO_STACK_SIZE;
96
97 /* Create the client thread. */
98 tx_thread_create(&ntest_2, "thread 2", ntest_2_entry, 0,
99 pointer, DEMO_STACK_SIZE,
100 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
101
102 pointer = pointer + DEMO_STACK_SIZE;
103
104 /* Initialize the NetX system. */
105 nx_system_initialize();
106
107 /* Create a packet pool. */
108 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", PACKET_SIZE, pointer, PACKET_POOL_SIZE);
109 pointer = pointer + PACKET_POOL_SIZE;
110 CHECK_STATUS(0, status);
111
112 /* Create server IP instance. */
113 status = nx_ip_create(&ip_0, "NetX IP Instance 0", RTP_SERVER_ADDRESS, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
114 pointer, 2048, 1);
115 pointer = pointer + 2048;
116 CHECK_STATUS(0, status);
117
118 /* Create client IP instance. */
119 status = nx_ip_create(&ip_1, "NetX IP Instance 1", RTP_CLIENT_1_ADDRESS, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
120 pointer, 2048, 1);
121 pointer = pointer + 2048;
122 CHECK_STATUS(0, status);
123
124 /* Create client IP instance. */
125 status = nx_ip_create(&ip_2, "NetX IP Instance 2", RTP_CLIENT_2_ADDRESS, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
126 pointer, 2048, 1);
127 pointer = pointer + 2048;
128 CHECK_STATUS(0, status);
129
130 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
131 status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
132 pointer = pointer + 1024;
133 CHECK_STATUS(0, status);
134
135 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
136 status = nx_arp_enable(&ip_1, (void *) pointer, 1024);
137 pointer = pointer + 1024;
138 CHECK_STATUS(0, status);
139
140 /* Enable ARP and supply ARP cache memory for IP Instance 2. */
141 status = nx_arp_enable(&ip_2, (void *) pointer, 1024);
142 pointer = pointer + 1024;
143 CHECK_STATUS(0, status);
144
145 /* Enable UDP processing for all IP instances. */
146 status = nx_udp_enable(&ip_0);
147 status += nx_udp_enable(&ip_1);
148 status += nx_udp_enable(&ip_2);
149 CHECK_STATUS(0, status);
150
151 /* Create semaphores for test done notification */
152 tx_semaphore_create(&semaphore_test_1_done, "semaphore test 1", 0);
153 tx_semaphore_create(&semaphore_test_2_done, "semaphore test 2", 0);
154 }
155
156 /* Define server threads. */
ntest_0_entry(ULONG thread_input)157 static void ntest_0_entry(ULONG thread_input)
158 {
159 UINT status;
160 NXD_ADDRESS client_ip_address;
161 NX_PACKET *send_packet;
162 UINT time_start;
163
164
165 /* Enable IGMP & join in multicast group. */
166 status = nx_igmp_enable(&ip_0);
167 status = nx_igmp_multicast_join(&ip_0, DEMO_MULTICAST_IP_ADDRESS);
168 CHECK_STATUS(0, status);
169
170 /* Create RTP sender. */
171 status = nx_rtp_sender_create(&rtp_0, &ip_0, &pool_0, CNAME, sizeof(CNAME) - 1);
172 CHECK_STATUS(0, status);
173
174 /* Get the udp port pair for rtp and rtcp */
175 status = nx_rtp_sender_port_get(&rtp_0, &rtp_port, &rtcp_port);
176 CHECK_STATUS(0, status);
177
178 /* Setup rtp sender session. */
179 client_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
180 client_ip_address.nxd_ip_address.v4 = DEMO_MULTICAST_IP_ADDRESS;
181 status = nx_rtp_sender_session_create(&rtp_0, &rtp_session_0, RTP_PAYLOAD_TYPE,
182 0, &client_ip_address,
183 RTP_CLIENT_RTP_PORT, RTP_CLIENT_RTCP_PORT);
184 CHECK_STATUS(0, status);
185
186 /* Wait for client threads ready. */
187 tx_thread_sleep(20);
188
189 /* Begin test cycles */
190 for (UINT i = 0; i < TEST_CYCLES; i++)
191 {
192
193 /* Allocate a packet */
194 status = nx_rtp_sender_session_packet_allocate(&rtp_session_0, &send_packet, 5 * NX_IP_PERIODIC_RATE);
195 CHECK_STATUS(0, status);
196
197 /* Copy payload data into the packet. */
198 status = nx_packet_data_append(send_packet, (void*)test_rtp_packet_data, sizeof(test_rtp_packet_data), rtp_0.nx_rtp_sender_ip_ptr->nx_ip_default_packet_pool, 5 * NX_IP_PERIODIC_RATE);
199 CHECK_STATUS(0, status);
200
201 status = nx_rtp_sender_session_packet_send(&rtp_session_0, send_packet, TEST_TIMESTAMP, TEST_MSW, TEST_LSW, 1);
202 CHECK_STATUS(0, status);
203 }
204
205 /* Wait for the check in test thread 1 done. */
206 status = tx_semaphore_get(&semaphore_test_1_done, 5 * NX_IP_PERIODIC_RATE);
207 CHECK_STATUS(0, status);
208
209 /* Wait for the check in test thread 2 done. */
210 status = tx_semaphore_get(&semaphore_test_2_done, 5 * NX_IP_PERIODIC_RATE);
211 CHECK_STATUS(0, status);
212
213 /* Delete and release resources */
214 status = nx_rtp_sender_session_delete(&rtp_session_0);
215 CHECK_STATUS(0, status);
216
217 status = nx_rtp_sender_delete(&rtp_0);
218 CHECK_STATUS(0, status);
219
220 /* Check if there is memory leak. */
221 CHECK_STATUS(pool_0.nx_packet_pool_total, pool_0.nx_packet_pool_available);
222
223 /* Return the test result. */
224 printf("SUCCESS!\n");
225 test_control_return(0);
226 }
227
228 /* Define the first client threads. */
ntest_1_entry(ULONG thread_input)229 static void ntest_1_entry(ULONG thread_input)
230 {
231 NX_PACKET *received_packet;
232 UINT status;
233 UCHAR *data;
234
235
236 /* Enable IGMP & join in multicast group. */
237 status = nx_igmp_enable(&ip_1);
238 status += nx_igmp_multicast_join(&ip_1, DEMO_MULTICAST_IP_ADDRESS);
239 CHECK_STATUS(0, status);
240
241 /* Create the rtp client socket. */
242 status = nx_udp_socket_create(&ip_1, &rtp_client_1_socket, "RTCP Client 1 Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
243 CHECK_STATUS(0, status);
244
245 status = nx_udp_socket_bind(&rtp_client_1_socket, RTP_CLIENT_RTP_PORT, NX_IP_PERIODIC_RATE);
246 CHECK_STATUS(0, status);
247
248 /* Begin test cycles */
249 for (UINT i = 0; i < TEST_CYCLES; i++)
250 {
251
252 /* Receive rtp data packet. */
253 status = nx_udp_socket_receive(&rtp_client_1_socket, &received_packet, 5 * TX_TIMER_TICKS_PER_SECOND);
254 CHECK_STATUS(0, status);
255
256 /* Validate RTP payload data */
257 data = received_packet -> nx_packet_prepend_ptr;
258
259 /* Check RTP version byte */
260 CHECK_STATUS(0x80, *data);
261
262 /* Move to check RTP data byte for payload type with marker */
263 data++;
264 CHECK_STATUS((0x80 | RTP_PAYLOAD_TYPE), *data);
265
266 /* Move to check RTP data bytes for sequence number */
267 data++;
268 CHECK_STATUS((rtp_session_0.nx_rtp_session_sequence_number - 1), (data[0] << 8 | data[1]));
269
270 /* Move to check RTP data bytes for time stamp */
271 data += 2;
272 CHECK_STATUS(rtp_session_0.nx_rtp_session_rtp_timestamp, (ULONG)(data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]));
273
274 /* Move to check RTP data bytes for ssrc */
275 data += 4;
276 CHECK_STATUS(rtp_session_0.nx_rtp_session_ssrc, (ULONG)(data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]));
277
278 /* Move to check RTP data bytes for data payload */
279 data += 4;
280 for (UINT i = 0; i < sizeof(test_rtp_packet_data); i++)
281 {
282 CHECK_STATUS(*(test_rtp_packet_data + i), data[i]);
283 }
284
285 /* Release the receive packet when the check finishes. */
286 nx_packet_release(received_packet);
287 }
288
289 /* Set the flag to notify test thread 0 that the check finishes. */
290 tx_semaphore_put(&semaphore_test_1_done);
291 }
292
293 /* Define the second client threads. */
ntest_2_entry(ULONG thread_input)294 static void ntest_2_entry(ULONG thread_input)
295 {
296 NX_PACKET *received_packet;
297 UINT status;
298 UCHAR *data;
299
300 /* Enable IGMP & join in multicast group. */
301 status = nx_igmp_enable(&ip_2);
302 status += nx_igmp_multicast_join(&ip_2, DEMO_MULTICAST_IP_ADDRESS);
303 CHECK_STATUS(0, status);
304
305 /* Create the rtp client socket. */
306 status = nx_udp_socket_create(&ip_2, &rtp_client_2_socket, "RTCP Client 2 Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
307 CHECK_STATUS(0, status);
308
309 status = nx_udp_socket_bind(&rtp_client_2_socket, RTP_CLIENT_RTP_PORT, NX_IP_PERIODIC_RATE);
310 CHECK_STATUS(0, status);
311
312 /* Begin test cycles */
313 for (UINT i = 0; i < TEST_CYCLES; i++)
314 {
315
316 /* Receive rtp data packet. */
317 status = nx_udp_socket_receive(&rtp_client_2_socket, &received_packet, 5 * TX_TIMER_TICKS_PER_SECOND);
318 CHECK_STATUS(0, status);
319
320 /* Validate RTP payload data */
321 data = received_packet -> nx_packet_prepend_ptr;
322
323 /* Check RTP version byte */
324 CHECK_STATUS(0x80, *data);
325
326 /* Move to check RTP data byte for payload type with marker */
327 data++;
328 CHECK_STATUS((0x80 | RTP_PAYLOAD_TYPE), *data);
329
330 /* Move to check RTP data bytes for sequence number */
331 data++;
332 CHECK_STATUS((rtp_session_0.nx_rtp_session_sequence_number - 1), (data[0] << 8 | data[1]));
333
334 /* Move to check RTP data bytes for time stamp */
335 data += 2;
336 CHECK_STATUS(rtp_session_0.nx_rtp_session_rtp_timestamp, (ULONG)(data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]));
337
338 /* Move to check RTP data bytes for ssrc */
339 data += 4;
340 CHECK_STATUS(rtp_session_0.nx_rtp_session_ssrc, (ULONG)(data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]));
341
342 /* Move to check RTP data bytes for data payload */
343 data += 4;
344 for (UINT i = 0; i < sizeof(test_rtp_packet_data); i++)
345 {
346 CHECK_STATUS(*(test_rtp_packet_data + i), data[i]);
347 }
348
349 /* Release the receive packet when the check finishes. */
350 nx_packet_release(received_packet);
351 }
352
353 /* Set the flag to notify test thread 0 that the check finishes. */
354 tx_semaphore_put(&semaphore_test_2_done);
355 }
356
357 #else
358
359 #ifdef CTEST
test_application_define(void * first_unused_memory)360 VOID test_application_define(void *first_unused_memory)
361 #else
362 void netx_rtp_multicast_test_application_define(void *first_unused_memory)
363 #endif
364 {
365
366 /* Print out test information banner. */
367 printf("NetX Test: RTP Multicast Test............................................N/A\n");
368
369 test_control_return(3);
370 }
371 #endif
372
373