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