mirror of
https://github.com/azure-rtos/netx.git
synced 2023-08-10 07:57:54 +08:00
522 lines
14 KiB
C
522 lines
14 KiB
C
/* This is a small demo of NetX FTP on the high-performance NetX TCP/IP stack. This demo
|
|
relies on ThreadX, NetX, and FileX to show a simple file transfer from the client
|
|
and then back to the server. */
|
|
|
|
|
|
|
|
#include "tx_api.h"
|
|
#include "fx_api.h"
|
|
#include "nx_api.h"
|
|
#include "nx_ftp_client.h"
|
|
#include "nx_ftp_server.h"
|
|
|
|
#define DEMO_STACK_SIZE 4096
|
|
#define DEMO_DATA "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
|
|
|
|
|
|
/* Uncomment the following line to enable passive transfer mode. */
|
|
/*
|
|
#define PASSIVE_MODE
|
|
*/
|
|
|
|
/* Uncomment the following line to enable block mode. */
|
|
/*
|
|
#define BLOCK_MODE
|
|
*/
|
|
|
|
|
|
/* Define the ThreadX, NetX, and FileX object control blocks... */
|
|
|
|
TX_THREAD server_thread;
|
|
TX_THREAD client_thread;
|
|
NX_PACKET_POOL server_pool;
|
|
NX_IP server_ip;
|
|
NX_PACKET_POOL client_pool;
|
|
NX_IP client_ip;
|
|
FX_MEDIA ram_disk;
|
|
|
|
|
|
/* Define the NetX FTP object control blocks. */
|
|
|
|
NX_FTP_CLIENT ftp_client;
|
|
NX_FTP_SERVER ftp_server;
|
|
|
|
|
|
/* Define the counters used in the demo application... */
|
|
|
|
ULONG error_counter = 0;
|
|
|
|
|
|
/* Define the memory area for the FileX RAM disk. */
|
|
|
|
UCHAR ram_disk_memory[32000];
|
|
UCHAR ram_disk_sector_cache[512];
|
|
|
|
|
|
#define FTP_SERVER_ADDRESS IP_ADDRESS(1,2,3,4)
|
|
#define FTP_CLIENT_ADDRESS IP_ADDRESS(1,2,3,5)
|
|
|
|
extern UINT _fx_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
|
|
CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
|
|
ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
|
|
UINT heads, UINT sectors_per_track);
|
|
|
|
/* Define the FileX and NetX driver entry functions. */
|
|
VOID _fx_ram_driver(FX_MEDIA *media_ptr);
|
|
|
|
/* Replace the 'ram' driver with your own Ethernet driver. */
|
|
VOID _nx_ram_network_driver(NX_IP_DRIVER *driver_req_ptr);
|
|
|
|
|
|
void client_thread_entry(ULONG thread_input);
|
|
void thread_server_entry(ULONG thread_input);
|
|
|
|
|
|
|
|
|
|
/* Define server login/logout functions. These are stubs for functions that would
|
|
validate a client login request. */
|
|
|
|
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);
|
|
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);
|
|
|
|
|
|
/* Define main entry point. */
|
|
|
|
int main()
|
|
{
|
|
|
|
/* Enter the ThreadX kernel. */
|
|
tx_kernel_enter();
|
|
return(0);
|
|
}
|
|
|
|
|
|
/* Define what the initial system looks like. */
|
|
|
|
void tx_application_define(void *first_unused_memory)
|
|
{
|
|
|
|
UINT status;
|
|
UCHAR *pointer;
|
|
|
|
/* Initialize NetX. */
|
|
nx_system_initialize();
|
|
|
|
/* Initialize FileX. */
|
|
fx_system_initialize();
|
|
|
|
/* Setup the working pointer. */
|
|
pointer = (UCHAR *) first_unused_memory;
|
|
|
|
/* Create a helper thread for the server. */
|
|
tx_thread_create(&server_thread, "FTP Server thread", thread_server_entry, 0,
|
|
pointer, DEMO_STACK_SIZE,
|
|
4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
|
|
|
|
pointer = pointer + DEMO_STACK_SIZE;
|
|
|
|
/* Create the packet pool for the FTP Server. */
|
|
status = nx_packet_pool_create(&server_pool, "NetX Server Packet Pool", 512, pointer, 8192);
|
|
pointer = pointer + 8192;
|
|
|
|
/* Check for errors. */
|
|
if (status)
|
|
error_counter++;
|
|
|
|
/* Create the IP instance for the FTP Server. */
|
|
status = nx_ip_create(&server_ip, "NetX Server IP Instance", FTP_SERVER_ADDRESS, 0xFFFFFF00UL,
|
|
&server_pool, _nx_ram_network_driver, pointer, 2048, 1);
|
|
pointer = pointer + 2048;
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
/* Enable ARP and supply ARP cache memory for server IP instance. */
|
|
nx_arp_enable(&server_ip, (void *) pointer, 1024);
|
|
pointer = pointer + 1024;
|
|
|
|
/* Enable TCP. */
|
|
nx_tcp_enable(&server_ip);
|
|
|
|
/* Create the FTP server. */
|
|
status = nx_ftp_server_create(&ftp_server, "FTP Server Instance", &server_ip, &ram_disk, pointer, DEMO_STACK_SIZE, &server_pool,
|
|
server_login, server_logout);
|
|
pointer = pointer + DEMO_STACK_SIZE;
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
/* Now set up the FTP Client. */
|
|
|
|
/* Create the main FTP client thread. */
|
|
status = tx_thread_create(&client_thread, "FTP Client thread ", client_thread_entry, 0,
|
|
pointer, DEMO_STACK_SIZE,
|
|
6, 6, TX_NO_TIME_SLICE, TX_AUTO_START);
|
|
pointer = pointer + DEMO_STACK_SIZE ;
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
/* Create a packet pool for the FTP client. */
|
|
status = nx_packet_pool_create(&client_pool, "NetX Client Packet Pool", 512, pointer, 8192);
|
|
pointer = pointer + 8192;
|
|
|
|
/* Create an IP instance for the FTP client. */
|
|
status = nx_ip_create(&client_ip, "NetX Client IP Instance", FTP_CLIENT_ADDRESS, 0xFFFFFF00UL,
|
|
&client_pool, _nx_ram_network_driver, pointer, 2048, 1);
|
|
pointer = pointer + 2048;
|
|
|
|
/* Enable ARP and supply ARP cache memory for the FTP Client IP. */
|
|
nx_arp_enable(&client_ip, (void *) pointer, 1024);
|
|
pointer = pointer + 1024;
|
|
|
|
/* Enable TCP for client IP instance. */
|
|
nx_tcp_enable(&client_ip);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* Define the FTP client thread. */
|
|
|
|
void client_thread_entry(ULONG thread_input)
|
|
{
|
|
|
|
NX_PACKET *my_packet;
|
|
NX_PACKET *recv_packet_ptr;
|
|
UINT status;
|
|
ULONG file_size;
|
|
|
|
|
|
NX_PARAMETER_NOT_USED(thread_input);
|
|
|
|
/* Format the RAM disk - the memory for the RAM disk was defined above. */
|
|
status = _fx_media_format(&ram_disk,
|
|
_fx_ram_driver, /* Driver entry */
|
|
ram_disk_memory, /* RAM disk memory pointer */
|
|
ram_disk_sector_cache, /* Media buffer pointer */
|
|
sizeof(ram_disk_sector_cache), /* Media buffer size */
|
|
"MY_RAM_DISK", /* Volume Name */
|
|
1, /* Number of FATs */
|
|
32, /* Directory Entries */
|
|
0, /* Hidden sectors */
|
|
256, /* Total sectors */
|
|
128, /* Sector size */
|
|
1, /* Sectors per cluster */
|
|
1, /* Heads */
|
|
1); /* Sectors per track */
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
/* Open the RAM disk. */
|
|
status = fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory, ram_disk_sector_cache, sizeof(ram_disk_sector_cache));
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
/* Let the IP threads and driver initialize the system. */
|
|
tx_thread_sleep(NX_IP_PERIODIC_RATE);
|
|
|
|
|
|
/* Create an FTP client. */
|
|
status = nx_ftp_client_create(&ftp_client, "FTP Client", &client_ip, 2000, &client_pool);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
printf("Created the FTP Client\n");
|
|
|
|
|
|
/* Now connect with the NetX FTP (IPv4) server. */
|
|
status = nx_ftp_client_connect(&ftp_client, FTP_SERVER_ADDRESS, "name", "password", NX_IP_PERIODIC_RATE);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
printf("Connected to the FTP Server\n");
|
|
|
|
#ifdef PASSIVE_MODE
|
|
/* Enable passive mode. */
|
|
status = nx_ftp_client_passive_mode_set(&ftp_client, NX_TRUE);
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
printf("Enabled FTP Client Passive Mode\n");
|
|
#endif /* PASSIVE_MODE */
|
|
|
|
#ifdef BLOCK_MODE
|
|
/* Set block mode. */
|
|
status = nx_ftp_client_transfer_mode_set(&ftp_client, NX_FTP_TRANSFER_MODE_BLOCK);
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
printf("Enabled FTP Client Block Mode\n");
|
|
#endif /* BLOCK_MODE */
|
|
|
|
/* Open a FTP file for writing. */
|
|
status = nx_ftp_client_file_open(&ftp_client, "test.txt", NX_FTP_OPEN_FOR_WRITE, NX_IP_PERIODIC_RATE);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
printf("Opened the FTP client test.txt file\n");
|
|
|
|
#ifdef BLOCK_MODE
|
|
/* Set the file size in block mode. */
|
|
status = nx_ftp_client_file_size_set(&ftp_client, 28);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
}
|
|
else
|
|
printf("Set the File Size in Block Mode\n");
|
|
#endif /* BLOCK_MODE */
|
|
|
|
/* Allocate a FTP packet. */
|
|
status = nx_packet_allocate(&client_pool, &my_packet, NX_TCP_PACKET, NX_IP_PERIODIC_RATE);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
/* Write ABCs into the packet payload! */
|
|
memcpy(my_packet -> nx_packet_prepend_ptr, DEMO_DATA, sizeof(DEMO_DATA)); /* Use case of memcpy is verified. */
|
|
|
|
/* Adjust the write pointer. */
|
|
my_packet -> nx_packet_length = sizeof(DEMO_DATA);
|
|
my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + sizeof(DEMO_DATA);
|
|
|
|
/* Write the packet to the file test.txt. */
|
|
status = nx_ftp_client_file_write(&ftp_client, my_packet, NX_IP_PERIODIC_RATE);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
nx_packet_release(my_packet);
|
|
return;
|
|
}
|
|
else
|
|
printf("Wrote to the FTP client test.txt file\n");
|
|
|
|
|
|
/* Close the file. */
|
|
status = nx_ftp_client_file_close(&ftp_client, NX_IP_PERIODIC_RATE);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
else
|
|
printf("Closed the FTP client test.txt file\n");
|
|
|
|
|
|
/* Now open the same file for reading. */
|
|
status = nx_ftp_client_file_open(&ftp_client, "test.txt", NX_FTP_OPEN_FOR_READ, NX_IP_PERIODIC_RATE);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
else
|
|
printf("Reopened the FTP client test.txt file\n");
|
|
|
|
/* Loop to read the data. */
|
|
file_size = 0;
|
|
do
|
|
{
|
|
|
|
/* Read the file. */
|
|
status = nx_ftp_client_file_read(&ftp_client, &my_packet, 100);
|
|
|
|
/* Check status. */
|
|
if (status == NX_SUCCESS)
|
|
{
|
|
file_size += my_packet -> nx_packet_length;
|
|
nx_packet_release(my_packet);
|
|
}
|
|
} while(status == NX_SUCCESS);
|
|
|
|
/* Check file size. */
|
|
if (file_size != 28)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
printf("Reread the FTP client test.txt file\n");
|
|
}
|
|
|
|
/* Close this file. */
|
|
status = nx_ftp_client_file_close(&ftp_client, NX_IP_PERIODIC_RATE);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
else
|
|
printf("Reclosed the FTP client test.txt file\n");
|
|
|
|
/* Get directory listing (NLST). */
|
|
status = nx_ftp_client_directory_listing_get(&ftp_client, "", &my_packet, 200);
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
nx_packet_release(my_packet);
|
|
}
|
|
|
|
do
|
|
{
|
|
/* Receive the next data packet. */
|
|
status = nx_ftp_client_directory_listing_continue(&ftp_client, &recv_packet_ptr, 200);
|
|
if (status == NX_SUCCESS)
|
|
{
|
|
nx_packet_release(recv_packet_ptr);
|
|
}
|
|
|
|
/* Check if this is the end of the download. */
|
|
if (status == NX_FTP_END_OF_LISTING)
|
|
break;
|
|
|
|
} while (status == NX_SUCCESS);
|
|
|
|
printf("Got the directory list test.txt\n");
|
|
|
|
/* Disconnect from the server. */
|
|
status = nx_ftp_client_disconnect(&ftp_client, NX_IP_PERIODIC_RATE);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
|
|
/* Delete the FTP client. */
|
|
status = nx_ftp_client_delete(&ftp_client);
|
|
|
|
/* Check status. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
error_counter++;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/* Define the helper FTP server thread. */
|
|
void thread_server_entry(ULONG thread_input)
|
|
{
|
|
|
|
UINT status;
|
|
|
|
NX_PARAMETER_NOT_USED(thread_input);
|
|
|
|
/* Wait till the IP thread and driver have initialized the system. */
|
|
tx_thread_sleep(NX_IP_PERIODIC_RATE);
|
|
|
|
|
|
/* OK to start the FTP Server. */
|
|
status = nx_ftp_server_start(&ftp_server);
|
|
|
|
if (status != NX_SUCCESS)
|
|
error_counter++;
|
|
|
|
printf("Server started!\n");
|
|
|
|
/* FTP server ready to take requests! */
|
|
|
|
/* Let the IP threads execute. */
|
|
tx_thread_relinquish();
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
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)
|
|
{
|
|
NX_PARAMETER_NOT_USED(ftp_server_ptr);
|
|
NX_PARAMETER_NOT_USED(client_ip_address);
|
|
NX_PARAMETER_NOT_USED(client_port);
|
|
NX_PARAMETER_NOT_USED(name);
|
|
NX_PARAMETER_NOT_USED(password);
|
|
NX_PARAMETER_NOT_USED(extra_info);
|
|
|
|
printf("Logged in!\n");
|
|
/* Always return success. */
|
|
return(NX_SUCCESS);
|
|
}
|
|
|
|
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)
|
|
{
|
|
NX_PARAMETER_NOT_USED(ftp_server_ptr);
|
|
NX_PARAMETER_NOT_USED(client_ip_address);
|
|
NX_PARAMETER_NOT_USED(client_port);
|
|
NX_PARAMETER_NOT_USED(name);
|
|
NX_PARAMETER_NOT_USED(password);
|
|
NX_PARAMETER_NOT_USED(extra_info);
|
|
|
|
printf("Logged out!\n");
|
|
|
|
/* Always return success. */
|
|
return(NX_SUCCESS);
|
|
}
|