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