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