1
2 #include "tx_api.h"
3 #include "nx_api.h"
4 #include "nxd_tftp_client.h"
5 #include "nxd_tftp_server.h"
6 #include "fx_api.h"
7
8 extern void test_control_return(UINT);
9
10 #if !defined(NX_DISABLE_IPV4)
11
12 #define DEMO_STACK_SIZE 4096
13
14 /* Define the ThreadX, NetX, and FileX object control blocks... */
15
16 static TX_THREAD server_thread;
17 static TX_THREAD client_thread;
18 static NX_PACKET_POOL server_pool;
19 static NX_IP server_ip;
20 static NX_PACKET_POOL client_pool;
21 static NX_IP client_ip;
22 static FX_MEDIA ram_disk;
23
24 /* Define the NetX DUO TFTP object control blocks. */
25
26 static NX_TFTP_CLIENT client;
27 static NX_TFTP_SERVER server;
28
29 /* Define the application global variables */
30
31 #define CLIENT_ADDRESS IP_ADDRESS(1, 2, 3, 5)
32 #define SERVER_ADDRESS IP_ADDRESS(1, 2, 3, 4)
33 #ifdef __PRODUCT_NETXDUO__
34 #define IP_TYPE 4
35 static NXD_ADDRESS server_ip_address;
36 #else
37 static ULONG server_ip_address;
38 #endif
39 static UINT error_counter = 0;
40
41 /* Define buffer used in the demo application. */
42 static UCHAR buffer[255];
43 static ULONG data_length;
44
45
46 /* Define the memory area for the FileX RAM disk. */
47 static UCHAR ram_disk_memory[32000];
48 static UCHAR ram_disk_sector_cache[512];
49
50
51 /* Define function prototypes. */
52
53 extern void _fx_ram_driver(FX_MEDIA *media_ptr);
54 extern void _nx_ram_network_driver_512(NX_IP_DRIVER *driver_req_ptr);
55
56 static void client_thread_entry(ULONG thread_input);
57 static void server_thread_entry(ULONG thread_input);
58
59
60 #ifdef CTEST
test_application_define(void * first_unused_memory)61 VOID test_application_define(void *first_unused_memory)
62 #else
63 void netx_tftp_basic_test_application_define(void *first_unused_memory)
64 #endif
65 {
66
67 UINT status;
68 UCHAR *pointer;
69
70
71 /* Setup the working pointer. */
72 pointer = (UCHAR *) first_unused_memory;
73
74 /* Create the main TFTPv6 server thread. */
75 status = tx_thread_create(&server_thread, "TFTP Server Thread", server_thread_entry, 0,
76 pointer, DEMO_STACK_SIZE,
77 4,4, TX_NO_TIME_SLICE, TX_AUTO_START);
78
79 pointer += DEMO_STACK_SIZE ;
80
81 /* Check for errors. */
82 if (status)
83 error_counter++;
84
85
86 /* Create the main TFTPv6 client thread at a slightly lower priority. */
87 status = tx_thread_create(&client_thread, "TFTP Client Thread", client_thread_entry, 0,
88 pointer, DEMO_STACK_SIZE,
89 5, 5, TX_NO_TIME_SLICE, TX_DONT_START);
90
91 pointer += DEMO_STACK_SIZE ;
92
93 /* Check for errors. */
94 if (status)
95 error_counter++;
96
97 /* Initialize the NetX system. */
98 nx_system_initialize();
99
100 /* Note: The data portion of a packet is exactly 512 bytes, but the packet payload size must
101 be at least 580 bytes. The remaining bytes are used for the UDP, IP, and Ethernet
102 headers and byte alignment requirements. */
103
104 status = nx_packet_pool_create(&server_pool, "TFTP Server Packet Pool", NX_TFTP_PACKET_SIZE, pointer, 8192);
105 pointer = pointer + 8192;
106
107 /* Check for errors. */
108 if (status)
109 error_counter++;
110
111 /* Create the IP instance for the TFTP Server. */
112 status = nx_ip_create(&server_ip, "NetX Server IP Instance", SERVER_ADDRESS, 0xFFFFFF00UL,
113 &server_pool, _nx_ram_network_driver_512, pointer, 2048, 1);
114 pointer = pointer + 2048;
115
116 /* Check for errors. */
117 if (status)
118 error_counter++;
119
120 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
121 status = nx_arp_enable(&server_ip, (void *) pointer, 1024);
122 pointer = pointer + 1024;
123
124 /* Check for errors. */
125 if (status)
126 error_counter++;
127
128 /* Enable UDP. */
129 status = nx_udp_enable(&server_ip);
130
131 /* Check for errors. */
132 if (status)
133 error_counter++;
134
135
136 /* Create the TFTP server. */
137 #ifdef __PRODUCT_NETXDUO__
138 server_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
139 server_ip_address.nxd_ip_address.v4 = SERVER_ADDRESS;
140 #else
141 server_ip_address = SERVER_ADDRESS;
142 #endif
143
144 #ifdef __PRODUCT_NETXDUO__
145 status = nxd_tftp_server_create(&server, "TFTP Server Instance", &server_ip, &ram_disk,
146 pointer, DEMO_STACK_SIZE, &server_pool);
147 #else
148 status = nx_tftp_server_create(&server, "TFTP Server Instance", &server_ip, &ram_disk,
149 pointer, DEMO_STACK_SIZE, &server_pool);
150 #endif
151
152 pointer = pointer + DEMO_STACK_SIZE;
153
154 /* Check for errors for the server. */
155 if (status)
156 error_counter++;
157
158 /* Create a packet pool for the TFTP client. */
159
160 /* Note: The data portion of a packet is exactly 512 bytes, but the packet payload size must
161 be at least 580 bytes. The remaining bytes are used for the UDP, IP, and Ethernet
162 headers and byte alignment requirements. */
163
164 status = nx_packet_pool_create(&client_pool, "TFTP Client Packet Pool", NX_TFTP_PACKET_SIZE, pointer, 8192);
165 pointer = pointer + 8192;
166
167 /* Check for errors. */
168 if (status)
169 error_counter++;
170
171 /* Create an IP instance for the TFTP client. */
172 status = nx_ip_create(&client_ip, "TFTP Client IP Instance", CLIENT_ADDRESS, 0xFFFFFF00UL,
173 &client_pool, _nx_ram_network_driver_512, pointer, 2048, 1);
174 pointer = pointer + 2048;
175
176 /* Check for errors. */
177 if (status)
178 error_counter++;
179
180 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
181 status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
182 pointer = pointer + 1024;
183
184 /* Enable UDP for client IP instance. */
185 status += nx_udp_enable(&client_ip);
186 status += nx_icmp_enable(&client_ip);
187
188 /* Check for errors. */
189 if (status)
190 error_counter++;
191
192 tx_thread_resume(&client_thread);
193 }
194
server_thread_entry(ULONG thread_input)195 void server_thread_entry(ULONG thread_input)
196 {
197
198 UINT status;
199
200 /* Print out test information banner. */
201 printf("NetX Test: TFTP Basic Test...........................................");
202
203 /* Check for earlier error. */
204 if(error_counter)
205 {
206 printf("ERROR!\n");
207 test_control_return(1);
208 }
209
210 /* Format the RAM disk - the memory for the RAM disk was defined above. */
211 status = fx_media_format(&ram_disk,
212 _fx_ram_driver, /* Driver entry */
213 ram_disk_memory, /* RAM disk memory pointer */
214 ram_disk_sector_cache, /* Media buffer pointer */
215 sizeof(ram_disk_sector_cache), /* Media buffer size */
216 "MY_RAM_DISK", /* Volume Name */
217 1, /* Number of FATs */
218 32, /* Directory Entries */
219 0, /* Hidden sectors */
220 256, /* Total sectors */
221 128, /* Sector size */
222 1, /* Sectors per cluster */
223 1, /* Heads */
224 1); /* Sectors per track */
225
226 /* Check for errors. */
227 if (status)
228 error_counter++;
229
230 /* Open the RAM disk. */
231 status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory, ram_disk_sector_cache, sizeof(ram_disk_sector_cache));
232
233 /* Check for errors. */
234 if (status)
235 error_counter++;
236
237 /* Start the NetX Duo TFTP server. */
238 #ifdef __PRODUCT_NETXDUO__
239 status = nxd_tftp_server_start(&server);
240 #else
241 status = nx_tftp_server_start(&server);
242 #endif
243
244 /* Check for errors. */
245 if (status)
246 error_counter++;
247
248 /* Run for a while */
249 tx_thread_sleep(3 * NX_IP_PERIODIC_RATE);
250
251 #ifdef __PRODUCT_NETXDUO__
252 nxd_tftp_server_delete(&server);
253 #else
254 nx_tftp_server_delete(&server);
255 #endif
256
257 if(error_counter)
258 {
259 printf("ERROR!\n");
260 test_control_return(1);
261 }
262 else
263 {
264 printf("SUCCESS!\n");
265 test_control_return(0);
266 }
267 }
268
269 /* Define the TFTP client thread. */
270
client_thread_entry(ULONG thread_input)271 void client_thread_entry(ULONG thread_input)
272 {
273
274 NX_PACKET *my_packet;
275 UINT status;
276 UINT all_done = NX_FALSE;
277
278
279 /* The TFTP services used below include the NetX equivalent service which will work with
280 NetX Duo TFTP. However, it is recommended for developers to port their applications
281 to the newer services that take the NXD_ADDRESS type and support both IPv4 and IPv6
282 communication.
283 */
284
285 /* Create a TFTP client. */
286 #ifdef __PRODUCT_NETXDUO__
287 status = nxd_tftp_client_create(&client, "TFTP Client", &client_ip, &client_pool, IP_TYPE);
288 #else
289 status = nx_tftp_client_create(&client, "TFTP Client", &client_ip, &client_pool);
290 #endif
291
292 /* Check status. */
293 if (status)
294 error_counter++;
295
296 /* Open a TFTP file for writing. */
297 #ifdef __PRODUCT_NETXDUO__
298 status = nxd_tftp_client_file_open(&client, "test.txt", &server_ip_address, NX_TFTP_OPEN_FOR_WRITE, NX_IP_PERIODIC_RATE, IP_TYPE);
299 #else
300 status = nx_tftp_client_file_open(&client, "test.txt", SERVER_ADDRESS, NX_TFTP_OPEN_FOR_WRITE, NX_IP_PERIODIC_RATE);
301 #endif
302
303 /* Check status. */
304 if (status)
305 error_counter++;
306
307 /* Allocate a TFTP packet. */
308 #ifdef __PRODUCT_NETXDUO__
309 status = nxd_tftp_client_packet_allocate(&client_pool, &my_packet, NX_IP_PERIODIC_RATE, IP_TYPE);
310 #else
311 status = nx_tftp_client_packet_allocate(&client_pool, &my_packet, NX_IP_PERIODIC_RATE);
312 #endif
313 /* Check status. */
314 if (status)
315 error_counter++;
316
317 /* Write ABCs into the packet payload! */
318 memcpy(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ ", 28);
319
320 /* Adjust the write pointer. */
321 my_packet -> nx_packet_length = 28;
322 my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + 28;
323
324 /* Write this packet to the file via TFTP. */
325 #ifdef __PRODUCT_NETXDUO__
326 status = nxd_tftp_client_file_write(&client, my_packet, NX_IP_PERIODIC_RATE, IP_TYPE);
327 #else
328 status = nx_tftp_client_file_write(&client, my_packet, NX_IP_PERIODIC_RATE);
329 #endif
330
331 /* Check status. */
332 if (status)
333 error_counter++;
334
335 /* Close this file. */
336 #ifdef __PRODUCT_NETXDUO__
337 status = nxd_tftp_client_file_close(&client, IP_TYPE);
338 #else
339 status = nx_tftp_client_file_close(&client);
340 #endif
341
342 /* Check status. */
343 if (status)
344 error_counter++;
345
346 /* Open the same file for reading. */
347 #ifdef __PRODUCT_NETXDUO__
348 status = nxd_tftp_client_file_open(&client, "test.txt", &server_ip_address, NX_TFTP_OPEN_FOR_READ, NX_IP_PERIODIC_RATE, IP_TYPE);
349 #else
350 status = nx_tftp_client_file_open(&client, "test.txt", SERVER_ADDRESS, NX_TFTP_OPEN_FOR_READ, NX_IP_PERIODIC_RATE);
351 #endif
352
353 /* Check status. */
354 if (status)
355 error_counter++;
356 do
357 {
358
359 /* Read the file back. */
360 #ifdef __PRODUCT_NETXDUO__
361 status = nxd_tftp_client_file_read(&client, &my_packet, NX_IP_PERIODIC_RATE, IP_TYPE);
362 #else
363 status = nx_tftp_client_file_read(&client, &my_packet, NX_IP_PERIODIC_RATE);
364 #endif
365 /* Check for retranmission/dropped packet error. Benign. Try again... */
366 if (status == NX_TFTP_INVALID_BLOCK_NUMBER)
367 {
368 continue;
369 }
370 else if (status == NX_TFTP_END_OF_FILE)
371 {
372 /* All done. */
373 all_done = NX_TRUE;
374 }
375 else if (status)
376 {
377 error_counter++;
378
379 /* Internal error, invalid packet or error on read. */
380 break;
381 }
382
383
384 /* Do something with the packet data and release when done. */
385 nx_packet_data_retrieve(my_packet, buffer, &data_length);
386 buffer[data_length] = 0;
387 nx_packet_release(my_packet);
388
389 } while (all_done == NX_FALSE);
390
391 /* Close the file again. */
392 #ifdef __PRODUCT_NETXDUO__
393 status = nxd_tftp_client_file_close(&client, IP_TYPE);
394 #else
395 status = nx_tftp_client_file_close(&client);
396 #endif
397
398 /* Check status. */
399 if (status)
400 error_counter++;
401
402 /* Delete the client. */
403 #ifdef __PRODUCT_NETXDUO__
404 status = nxd_tftp_client_delete(&client);
405 #else
406 status = nx_tftp_client_delete(&client);
407 #endif
408
409 /* Check status. */
410 if (status)
411 error_counter++;
412 }
413 #else
414
415 #ifdef CTEST
test_application_define(void * first_unused_memory)416 VOID test_application_define(void *first_unused_memory)
417 #else
418 void netx_tftp_basic_test_application_define(void *first_unused_memory)
419 #endif
420 {
421
422 /* Print out test information banner. */
423 printf("NetX Test: TFTP Basic Test...........................................N/A\n");
424
425 test_control_return(3);
426 }
427 #endif