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