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                10
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_ADDRESS         IP_ADDRESS(1,2,3,5)
18 #define RTP_CLIENT_RTP_PORT        6002
19 #define RTP_CLIENT_RTCP_PORT       6003
20 #define RTP_PAYLOAD_TYPE           96
21 #define CNAME                      "AzureRTOS@microsoft.com"
22 
23 /* Define test data. */
24 #define TEST_TIMESTAMP             1234
25 #define TEST_MSW                   123
26 #define TEST_LSW                   456
27 
28 static UCHAR test_rtp_packet_data[] = "test rtp packet data";
29 
30 /* Define the ThreadX object control blocks...  */
31 
32 static TX_THREAD                   ntest_0;
33 static TX_THREAD                   ntest_1;
34 
35 static NX_PACKET_POOL              pool_0;
36 static NX_IP                       ip_0;
37 static NX_IP                       ip_1;
38 static NX_UDP_SOCKET               rtp_client_socket;
39 
40 static TX_SEMAPHORE                semaphore_test_0_done;
41 static TX_SEMAPHORE                semaphore_test_1_done;
42 
43 /* Define rtp sender control block.  */
44 static NX_RTP_SENDER               rtp_0;
45 static NX_RTP_SESSION              rtp_session_0;
46 static UINT                        rtp_port;
47 static UINT                        rtcp_port;
48 
49 
50 /* Define thread prototypes.  */
51 
52 static void ntest_0_entry(ULONG thread_input);
53 static void ntest_1_entry(ULONG thread_input);
54 extern void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
55 extern void test_control_return(UINT status);
56 
57 #ifdef CTEST
test_application_define(void * first_unused_memory)58 VOID test_application_define(void *first_unused_memory)
59 #else
60 void    netx_rtp_basic_test_application_define(void *first_unused_memory)
61 #endif
62 {
63 
64 CHAR       *pointer;
65 UINT        status;
66 
67     /* Print out test information banner.  */
68     printf("NetX Test:   RTP Basic Test............................................");
69 
70     /* Setup the working pointer.  */
71     pointer = (CHAR *)first_unused_memory;
72 
73     /* Create the server thread.  */
74     tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
75                      pointer, DEMO_STACK_SIZE,
76                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
77 
78     pointer = pointer + DEMO_STACK_SIZE;
79 
80     /* Create the client thread.  */
81     tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
82                      pointer, DEMO_STACK_SIZE,
83                      3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
84 
85     pointer = pointer + DEMO_STACK_SIZE;
86 
87     /* Initialize the NetX system.  */
88     nx_system_initialize();
89 
90     /* Create a packet pool.  */
91     status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", PACKET_SIZE, pointer, PACKET_POOL_SIZE);
92     pointer = pointer + PACKET_POOL_SIZE;
93     CHECK_STATUS(0, status);
94 
95     /* Create server IP instance.  */
96     status = nx_ip_create(&ip_0, "NetX IP Instance 0", RTP_SERVER_ADDRESS, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
97                           pointer, 2048, 1);
98     pointer = pointer + 2048;
99     CHECK_STATUS(0, status);
100 
101     /* Create client IP instance.  */
102     status = nx_ip_create(&ip_1, "NetX IP Instance 1", RTP_CLIENT_ADDRESS, 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
103                           pointer, 2048, 1);
104     pointer = pointer + 2048;
105     CHECK_STATUS(0, status);
106 
107     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
108     status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
109     pointer = pointer + 1024;
110     CHECK_STATUS(0, status);
111 
112     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
113     status = nx_arp_enable(&ip_1, (void *) pointer, 1024);
114     pointer = pointer + 1024;
115     CHECK_STATUS(0, status);
116 
117     /* Enable UDP processing for both IP instances.  */
118     status = nx_udp_enable(&ip_0);
119     CHECK_STATUS(0, status);
120     status = nx_udp_enable(&ip_1);
121     CHECK_STATUS(0, status);
122 
123     /* Create semaphores for test done notification */
124     tx_semaphore_create(&semaphore_test_0_done, "semaphore test 0", 0);
125     tx_semaphore_create(&semaphore_test_1_done, "semaphore test 1", 0);
126 }
127 
128 /* Define server threads.  */
ntest_0_entry(ULONG thread_input)129 static void    ntest_0_entry(ULONG thread_input)
130 {
131 UINT        status;
132 NXD_ADDRESS client_ip_address;
133 NX_PACKET  *send_packet;
134 UINT        time_start;
135 
136 
137     /* Create RTP sender.  */
138     status = nx_rtp_sender_create(&rtp_0, &ip_0, &pool_0, CNAME, sizeof(CNAME) - 1);
139     CHECK_STATUS(0, status);
140 
141     /* Get the udp port pair for rtp and rtcp */
142     status = nx_rtp_sender_port_get(&rtp_0, &rtp_port, &rtcp_port);
143     CHECK_STATUS(0, status);
144 
145     /* Setup rtp sender session.  */
146     client_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
147     client_ip_address.nxd_ip_address.v4 = RTP_CLIENT_ADDRESS;
148     status = nx_rtp_sender_session_create(&rtp_0, &rtp_session_0, RTP_PAYLOAD_TYPE,
149                                           0, &client_ip_address,
150                                           RTP_CLIENT_RTP_PORT, RTP_CLIENT_RTCP_PORT);
151     CHECK_STATUS(0, status);
152 
153     /* If more than one rtp packet is sent during the first tick, rtcp packet will also be sent more than once.
154        To make a stable test result, wait for a tick here to avoid this situation. */
155     tx_thread_sleep(1);
156 
157     /* Allocate a packet */
158     status = nx_rtp_sender_session_packet_allocate(&rtp_session_0, &send_packet, 5 * NX_IP_PERIODIC_RATE);
159     CHECK_STATUS(0, status);
160 
161     /* Copy payload data into the packet. */
162     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);
163     CHECK_STATUS(0, status);
164 
165     status = nx_rtp_sender_session_packet_send(&rtp_session_0, send_packet, TEST_TIMESTAMP, TEST_MSW, TEST_LSW, 1);
166     CHECK_STATUS(0, status);
167 
168     /* Wait for the check in test thread 1 done. */
169     status = tx_semaphore_get(&semaphore_test_1_done, 5 * NX_IP_PERIODIC_RATE);
170     CHECK_STATUS(0, status);
171 
172     /* Delete and release resources */
173     status = nx_rtp_sender_session_delete(&rtp_session_0);
174     CHECK_STATUS(0, status);
175 
176     status = nx_rtp_sender_delete(&rtp_0);
177     CHECK_STATUS(0, status);
178 
179     /* Put the semaphore to notify thread 1 it is fine to check resource leakage. */
180     tx_semaphore_put(&semaphore_test_0_done);
181 }
182 
183 /* Define the client threads.  */
ntest_1_entry(ULONG thread_input)184 static void    ntest_1_entry(ULONG thread_input)
185 {
186 NX_PACKET *received_packet;
187 UINT       status;
188 UCHAR     *data;
189 
190 
191     /* Create the rtp client socket.  */
192     status = nx_udp_socket_create(&ip_1, &rtp_client_socket, "RTCP Client Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5);
193     CHECK_STATUS(0, status);
194 
195     status =  nx_udp_socket_bind(&rtp_client_socket, RTP_CLIENT_RTP_PORT, NX_IP_PERIODIC_RATE);
196     CHECK_STATUS(0, status);
197 
198     /* Receive rtp data packet. */
199     status = nx_udp_socket_receive(&rtp_client_socket, &received_packet, 5 * TX_TIMER_TICKS_PER_SECOND);
200     CHECK_STATUS(0, status);
201 
202     /* Validate RTP payload data */
203     data = received_packet -> nx_packet_prepend_ptr;
204 
205     /* Check RTP version byte */
206     CHECK_STATUS(0x80, *data);
207 
208     /* Move to check RTP data byte for payload type with marker */
209     data++;
210     CHECK_STATUS((0x80 | RTP_PAYLOAD_TYPE), *data);
211 
212     /* Move to check RTP data bytes for sequence number */
213     data++;
214     CHECK_STATUS((rtp_session_0.nx_rtp_session_sequence_number - 1), (data[0] << 8 | data[1]));
215 
216     /* Move to check RTP data bytes for time stamp */
217     data += 2;
218     CHECK_STATUS(rtp_session_0.nx_rtp_session_rtp_timestamp, (ULONG)(data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]));
219 
220     /* Move to check RTP data bytes for ssrc */
221     data += 4;
222     CHECK_STATUS(rtp_session_0.nx_rtp_session_ssrc, (ULONG)(data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]));
223 
224     /* Move to check RTP data bytes for data payload */
225     data += 4;
226     for (UINT i = 0; i < sizeof(test_rtp_packet_data); i++)
227     {
228         CHECK_STATUS(*(test_rtp_packet_data + i), data[i]);
229     }
230 
231     /* Release the receive packet when the check finishes. */
232     nx_packet_release(received_packet);
233 
234     /* Set the flag to notify test thread 0 that the check finishes. */
235     tx_semaphore_put(&semaphore_test_1_done);
236 
237     /* Wait for the check in test thread 0 done. */
238     status = tx_semaphore_get(&semaphore_test_0_done, 5 * NX_IP_PERIODIC_RATE);
239     CHECK_STATUS(0, status);
240 
241     /* Check if there is memory leak. */
242     CHECK_STATUS(pool_0.nx_packet_pool_total, pool_0.nx_packet_pool_available);
243 
244     /* Return the test result.  */
245     printf("SUCCESS!\n");
246     test_control_return(0);
247 }
248 
249 #else
250 
251 #ifdef CTEST
test_application_define(void * first_unused_memory)252 VOID test_application_define(void *first_unused_memory)
253 #else
254 void    netx_rtp_basic_test_application_define(void *first_unused_memory)
255 #endif
256 {
257 
258     /* Print out test information banner.  */
259     printf("NetX Test:   RTP Basic Test............................................N/A\n");
260 
261     test_control_return(3);
262 }
263 #endif
264 
265