1 /* No.4 Files are transferred only via the data connection.
2     rfc959,  page 9, 3. DATA TRANSFER FUNCTIONS */
3 #include    "tx_api.h"
4 #include    "fx_api.h"
5 #include    "nx_api.h"
6 #include    "nxd_ftp_client.h"
7 #include    "nxd_ftp_server.h"
8 
9 extern void     test_control_return(UINT);
10 
11 #if !defined(NX_DISABLE_IPV4)
12 
13 #define     DEMO_STACK_SIZE         4096
14 
15 /* Define the ThreadX, NetX, and FileX object control blocks...  */
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 static UINT                    data_control_counter;
24 
25 /* Define the NetX FTP object control blocks.  */
26 static NX_FTP_CLIENT           ftp_client;
27 static NX_FTP_SERVER           ftp_server;
28 
29 /* Define the counters used in the demo application...  */
30 static ULONG                   error_counter = 0;
31 static UINT                    test_done = NX_FALSE;
32 
33 /* Define the memory area for the FileX RAM disk.  */
34 static UCHAR                   ram_disk_memory[32000];
35 static UCHAR                   ram_disk_sector_cache[512];
36 
37 
38 #define FTP_SERVER_ADDRESS  IP_ADDRESS(1,2,3,4)
39 #define FTP_CLIENT_ADDRESS  IP_ADDRESS(1,2,3,5)
40 
41 extern UINT  _fx_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
42                               CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
43                               ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
44                               UINT heads, UINT sectors_per_track);
45 
46 /* Define the FileX and NetX driver entry functions.  */
47 extern void     _fx_ram_driver(FX_MEDIA *media_ptr);
48 extern void     _nx_ram_network_driver_512(NX_IP_DRIVER *driver_req_ptr);
49 
50 static void    client_thread_entry(ULONG thread_input);
51 static void    thread_server_entry(ULONG thread_input);
52 
53 
54 /* Define server login/logout functions.  These are stubs for functions that would
55 validate a client login request.   */
56 static UINT    server_login(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, ULONG client_ip_address, UINT client_port, CHAR *name, CHAR *password, CHAR *extra_info);
57 static UINT    server_logout(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, ULONG client_ip_address, UINT client_port, CHAR *name, CHAR *password, CHAR *extra_info);
58 
59 #ifdef CTEST
test_application_define(void * first_unused_memory)60 VOID test_application_define(void *first_unused_memory)
61 #else
62 void    netx_ftp_data_connection_test_application_define(void *first_unused_memory)
63 #endif
64 {
65 
66 UINT    status;
67 UCHAR   *pointer;
68 
69 
70     /* Setup the working pointer.  */
71     pointer =  (UCHAR *) first_unused_memory;
72 
73     /* Create a helper thread for the server. */
74     tx_thread_create(&server_thread, "FTP Server thread", thread_server_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     /* Initialize NetX.  */
81     nx_system_initialize();
82 
83     /* Create the packet pool for the FTP Server.  */
84     status = nx_packet_pool_create(&server_pool, "NetX Server Packet Pool", 512, pointer, 8192);
85     pointer = pointer + 8192;
86     if (status)
87         error_counter++;
88 
89     /* Create the IP instance for the FTP Server.  */
90     status = nx_ip_create(&server_ip, "NetX Server IP Instance", FTP_SERVER_ADDRESS, 0xFFFFFF00UL,
91                           &server_pool, _nx_ram_network_driver_512, pointer, 2048, 1);
92     pointer = pointer + 2048;
93     if (status)
94         error_counter++;
95 
96     /* Enable ARP and supply ARP cache memory for server IP instance.  */
97     status = nx_arp_enable(&server_ip, (void *) pointer, 1024);
98     pointer = pointer + 1024;
99     if (status)
100         error_counter++;
101 
102     /* Enable TCP.  */
103     status = nx_tcp_enable(&server_ip);
104     if (status)
105         error_counter++;
106 
107     /* Create the FTP server.  */
108     status =  nx_ftp_server_create(&ftp_server, "FTP Server Instance", &server_ip, &ram_disk, pointer, DEMO_STACK_SIZE, &server_pool,
109                                    server_login, server_logout);
110     pointer =  pointer + DEMO_STACK_SIZE;
111     if (status)
112         error_counter++;
113 
114     /* Now set up the FTP Client. */
115 
116     /* Create the main FTP client thread.  */
117     status = tx_thread_create(&client_thread, "FTP Client thread ", client_thread_entry, 0,
118                               pointer, DEMO_STACK_SIZE,
119                               6, 6, TX_NO_TIME_SLICE, TX_AUTO_START);
120     pointer = pointer + DEMO_STACK_SIZE ;
121     if (status)
122         error_counter++;
123 
124     /* Create a packet pool for the FTP client.  */
125     status =  nx_packet_pool_create(&client_pool, "NetX Client Packet Pool", 256, pointer, 8192);
126     pointer =  pointer + 8192;
127     if (status)
128         error_counter++;
129 
130     /* Create an IP instance for the FTP client.  */
131     status = nx_ip_create(&client_ip, "NetX Client IP Instance", FTP_CLIENT_ADDRESS, 0xFFFFFF00UL,
132                           &client_pool, _nx_ram_network_driver_512, pointer, 2048, 1);
133     pointer = pointer + 2048;
134     if (status)
135         error_counter++;
136 
137     /* Enable ARP and supply ARP cache memory for the FTP Client IP.  */
138     status = nx_arp_enable(&client_ip, (void *) pointer, 1024);
139     pointer = pointer + 1024;
140     if (status)
141         error_counter++;
142 
143     /* Enable TCP for client IP instance.  */
144     status = nx_tcp_enable(&client_ip);
145     if (status)
146         error_counter++;
147 
148 
149     data_control_counter = 0;
150 }
151 
152 /* Define the FTP client thread.  */
153 
client_thread_entry(ULONG thread_input)154 void    client_thread_entry(ULONG thread_input)
155 {
156 
157 NX_PACKET   *my_packet;
158 UINT        status;
159 
160     /* Format the RAM disk - the memory for the RAM disk was defined above.  */
161     status = _fx_media_format(&ram_disk,
162         _fx_ram_driver,                  /* Driver entry                */
163         ram_disk_memory,                 /* RAM disk memory pointer     */
164         ram_disk_sector_cache,           /* Media buffer pointer        */
165         sizeof(ram_disk_sector_cache),   /* Media buffer size           */
166         "MY_RAM_DISK",                   /* Volume Name                 */
167         1,                               /* Number of FATs              */
168         32,                              /* Directory Entries           */
169         0,                               /* Hidden sectors              */
170         256,                             /* Total sectors               */
171         128,                             /* Sector size                 */
172         1,                               /* Sectors per cluster         */
173         1,                               /* Heads                       */
174         1);                              /* Sectors per track           */
175 
176     /* Check status.  */
177     if (status)
178         error_counter++;
179 
180     /* Open the RAM disk.  */
181     status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory, ram_disk_sector_cache, sizeof(ram_disk_sector_cache));
182     if (status)
183         error_counter++;
184 
185     /* Create an FTP client.  */
186     status =  nx_ftp_client_create(&ftp_client, "FTP Client", &client_ip, 2000, &client_pool);
187     if (status)
188         error_counter++;
189 
190     /* Now connect with the NetX FTP (IPv4) server. */
191     status =  nx_ftp_client_connect(&ftp_client, FTP_SERVER_ADDRESS, "name", "password", NX_IP_PERIODIC_RATE);
192     if (status)
193         error_counter++;
194 
195     /* Open a FTP file for writing.  */
196     status =  nx_ftp_client_file_open(&ftp_client, "test.txt", NX_FTP_OPEN_FOR_WRITE, NX_IP_PERIODIC_RATE);
197     if (status)
198         error_counter++;
199 
200     /* Allocate a FTP packet.  */
201     status =  nx_packet_allocate(&client_pool, &my_packet, NX_TCP_PACKET, NX_IP_PERIODIC_RATE);
202     if (status)
203         error_counter++;
204 
205     /* Write ABCs into the packet payload!  */
206     memcpy(my_packet -> nx_packet_prepend_ptr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ  ", 28);
207 
208     /* Adjust the write pointer.  */
209     my_packet -> nx_packet_length =  28;
210     my_packet -> nx_packet_append_ptr =  my_packet -> nx_packet_prepend_ptr + 28;
211 
212     /* Write the packet to the file test.txt.  */
213     status =  nx_ftp_client_file_write(&ftp_client, my_packet, NX_IP_PERIODIC_RATE);
214     if (status)
215         error_counter++;
216 
217     /* Close the file.  */
218     status =  nx_ftp_client_file_close(&ftp_client, NX_IP_PERIODIC_RATE);
219     if (status)
220         error_counter++;
221 
222     /* Now open the same file for reading.  */
223     status =  nx_ftp_client_file_open(&ftp_client, "test.txt", NX_FTP_OPEN_FOR_READ, NX_IP_PERIODIC_RATE);
224     if (status)
225         error_counter++;
226 
227     /* Read the file.  */
228     status =  nx_ftp_client_file_read(&ftp_client, &my_packet, NX_IP_PERIODIC_RATE);
229     if (status)
230         error_counter++;
231     else
232     {
233         data_control_counter++;
234         nx_packet_release(my_packet);
235     }
236     /* Close this file.  */
237     status =  nx_ftp_client_file_close(&ftp_client, NX_IP_PERIODIC_RATE);
238     if (status)
239         error_counter++;
240 
241     status =  nx_ftp_client_file_open(&ftp_client, "test.txt", NX_FTP_OPEN_FOR_READ, NX_IP_PERIODIC_RATE);
242     if (status)
243         error_counter++;
244 
245     /* If after closing the client data socket we can also successfully transfer FTP commands, then we can make sure that the The control connection is used for the transfer of commands.*/
246     status = nx_tcp_socket_disconnect(&(ftp_client.nx_ftp_client_data_socket), NX_IP_PERIODIC_RATE);
247     if(status)
248         error_counter++;
249 
250     ftp_client.nx_ftp_client_data_socket.nx_tcp_socket_state = NX_TCP_CLOSED;
251 
252     nx_tcp_client_socket_unbind(&(ftp_client.nx_ftp_client_data_socket));
253     /* Check for error.  */
254     if(status)
255         error_counter++;
256 
257 
258     /* Delete the socket.  */
259     status = nx_tcp_socket_delete(&ftp_client.nx_ftp_client_data_socket);
260 
261     /* Check for error.  */
262     if(status)
263         error_counter++;
264 
265     /* Disconnect the data socket connection we can find that we cannot successfully transfer the files. */
266     /* Read the file.  */
267     status =  nx_ftp_client_file_read(&ftp_client, &my_packet, NX_IP_PERIODIC_RATE);
268     if (status == NX_NOT_BOUND)
269         data_control_counter++;
270     else
271     {
272         nx_packet_release(my_packet);
273     }
274 
275     /* Close this file.  */
276     status =  nx_ftp_client_file_close(&ftp_client, NX_IP_PERIODIC_RATE);
277     if (status)
278         error_counter++;
279 
280     /* Disconnect from the server.  */
281     status =  nx_ftp_client_disconnect(&ftp_client, NX_IP_PERIODIC_RATE);
282     if (status)
283         error_counter++;
284 
285     /* Delete the FTP client.  */
286     status =  nx_ftp_client_delete(&ftp_client);
287     if (status)
288         error_counter++;
289 
290     /* Set the flag.  */
291     test_done = NX_TRUE;
292 }
293 
294 
295 /* Define the helper FTP server thread.  */
thread_server_entry(ULONG thread_input)296 void    thread_server_entry(ULONG thread_input)
297 {
298 
299     UINT    status;
300 
301     /* Print out test information banner.  */
302     printf("NetX Test:   FTP Data Connection Test..................................");
303 
304     /* Check for earlier error. */
305     if(error_counter)
306     {
307         printf("ERROR!\n");
308         test_control_return(1);
309     }
310 
311     /* OK to start the FTPv6 Server.   */
312     status = nx_ftp_server_start(&ftp_server);
313     if (status)
314         error_counter++;
315 
316     /* Wait for test.  */
317     while(test_done == NX_FALSE)
318         tx_thread_sleep(NX_IP_PERIODIC_RATE);
319 
320     status = nx_ftp_server_delete(&ftp_server);
321     if(status)
322         error_counter++;
323 
324     if((error_counter != 0) || (data_control_counter != 2))
325     {
326         printf("ERROR!\n");
327         test_control_return(1);
328     }
329     else
330     {
331         printf("SUCCESS!\n");
332         test_control_return(0);
333     }
334 }
335 
336 
server_login(struct NX_FTP_SERVER_STRUCT * ftp_server_ptr,ULONG client_ip_address,UINT client_port,CHAR * name,CHAR * password,CHAR * extra_info)337 static UINT  server_login(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, ULONG client_ip_address, UINT client_port, CHAR *name, CHAR *password, CHAR *extra_info)
338 {
339     /* Always return success.  */
340     return(NX_SUCCESS);
341 }
342 
server_logout(struct NX_FTP_SERVER_STRUCT * ftp_server_ptr,ULONG client_ip_address,UINT client_port,CHAR * name,CHAR * password,CHAR * extra_info)343 static UINT  server_logout(struct NX_FTP_SERVER_STRUCT *ftp_server_ptr, ULONG client_ip_address, UINT client_port, CHAR *name, CHAR *password, CHAR *extra_info)
344 {
345     /* Always return success.  */
346     return(NX_SUCCESS);
347 }
348 #else
349 
350 #ifdef CTEST
test_application_define(void * first_unused_memory)351 VOID test_application_define(void *first_unused_memory)
352 #else
353 void    netx_ftp_data_connection_test_application_define(void *first_unused_memory)
354 #endif
355 {
356 
357     /* Print out test information banner.  */
358     printf("NetX Test:   FTP Data Connection Test..................................N/A\n");
359 
360     test_control_return(3);
361 }
362 #endif