Name
FTP Server API — describe FTP server API, callback and configuration
FTP Server API
The FTP server provides a single entry point:
#include <ftpserver.h> __externC int cyg_ftpserver_start( cyg_ftpserver *server );
This function starts an FTP server running using parameters defined
in the server
argument. It should be called
from a thread with a stack with at least
CYGNUM_NET_FTPSERVER_STACK_SIZE
bytes
available. Under normal circumstances this function will not
return, so the application should create a thread dedicated to the
server. There are examples of this in the test programs.
The server
argument contains a number of
fields that the user may set to control the behaviour of the FTP
server.
-
const char *address
- This is a string giving the IP address on which the server will listen. If not set this will default to listening on all network interface, which is usually what is wanted. This option is only useful if a target has more than one network interface and the FTP server should only listen on one of them.
-
int port
- This defines the port number on which the server will listen. Leaving this value unset, zero, will cause the server to choose the default FTP port of 21.
-
const char *greeting
- This is the string that the server will use in its initial response to a client connection. Leaving this NULL will cause the server to use a default message: "Welcome to eCosPro FTP service.".
-
const char *root
- This string defines a filesystem pathname to the root directory of the FTP server. Files will only be transferred to and from this directory or any subdirectories. A NULL pointer here will cause the server to use "/" as the root.
-
int data_port
- This defines the first port at which the server will create passive data connections. It will try successive ports from this value until a free port is found, limited to the following 20 ports. Leaving this value NULL will cause the server to start from port 5000.
The normal idiom for use of the FTP server is to define the
cyg_ftpserver structure statically and to then call
cyg_ftpserver_start()
with a pointer to
that. The following is a somewhat contrived example:
#include <ftpserver.h> //========================================================================== static cyg_ftpserver ftp_server = { .port = 2121, // Listen on port 2121 .root = "/fatfs/ftp", // FTP to/from here .greeting = "Welcome to Fubar FTP service.", // Welcome string .data_port = 40000 // Move data ports to 40000+ }; //========================================================================== static void ftpd(CYG_ADDRWORD p) { init_all_network_interfaces(); cyg_ftpserver_start( &ftp_server ); } //========================================================================== #define STACK_SIZE CYGNUM_NET_FTPSERVER_STACK_SIZE static char stack[STACK_SIZE] CYGBLD_ATTRIB_ALIGN_MAX; static cyg_thread thread_data; static cyg_handle_t thread_handle; void start_ftpd_thread(void) { cyg_thread_create(10, // Priority ftpd, // entry 0, // entry parameter "FTP test", // Name &stack[0], // Stack STACK_SIZE, // Size &thread_handle, // Handle &thread_data // Thread data structure ); cyg_thread_resume(thread_handle); /* Start it */ }
The defaults for the configuration parameters are such that leaving them all zero or NULL will cause the server to configure itself on the standard port serving files to/from the root of the filesystem.
Callback Interface
The default server operates to and from a directory in a filesystem, in the same way that most FTP servers operate. However, not all embedded systems have filesystem support. To allow such systems to provide an FTP service, all file access operations go through a set of callback functions in the cyg_ftpserver structure. The user can define these to redirect file I/O operations to other devices such as memory buffers or flash memory regions.
The callback interface defines a type, ftpserver_cookie that is passed to the callback functions. It is a word or pointer sized value and is typically used by the callback functions to contain a data structure pointer, or an index into a table that uniquely identifies an open file.
The callbacks for a notional example interface are defined as follows:
-
int example_open( const char *path, cyg_bool write, ftpserver_cookie *cookie );
Called to open a file for data transfer. The
path
is a fully rooted path formed from theroot
field of the server configuration plus the client supplied path. Thewrite
argument is true if the file is to be opened for writing and false if for reading. If successful the function may store a private value to*cookie
.If the file is opened successfully this function should return
FTPSERVER_OK
. If the file cannot be opened for reading it should returnFTPSERVER_NO_FILE
. If the file cannot be written to or created it should returnFTPSERVER_NOT_ALLOWED
.-
int example_write( ftpserver_cookie cookie, const cyg_uint8 *buf, cyg_uint32 size );
Called to write data to the file. The
cookie
argument is the value stored by the open callback. Argumentsbuf
andsize
define the data to be written.If the data is successfully written this function should return
FTPSERVER_OK
. If any error occurs it should returnFTPSERVER_WRITE_FAIL
.-
int example_read( ftpserver_cookie cookie, cyg_uint8 *buf, cyg_uint32 *size );
Called to read data from the file. The
cookie
argument is the value stored by the open callback. Argumentsbuf
and*size
define a buffer into which the data should be stored,*size
should be updated with the amount of data written to the buffer. If no more data is available,*size
should be set to zero.If the function is successful it should return
FTPSERVER_OK
. If any error occurs it should returnFTPSERVER_READ_FAIL
.-
int example_close( ftpserver_cookie cookie );
Called to close the file for further data transfer. The
cookie
argument is the value stored by the open callback. After this call the cookie value will not be used in further calls.This function should return
FTPSERVER_OK
under all circumstance, there are no error conditions of interest to the FTP server.-
int example_auth( const char *user, const char *passwd );
This function is called to authenticate a user ID and password supplied by the client. The FTP server will only request a password, by returning a 331 response, if a user supplied authentication function is installed.
If the user and password are accepted, this function should return
FTPSERVER_LOGIN_OK
; it should returnFTPSERVER_BADUSER
if they do not.-
int example_delete( const char *path );
Called to delete a file. The
path
is a fully rooted path formed from theroot
field of the server configuration plus the client supplied path.If the file is deleted successfully this function should return
FTPSERVER_OPDONE
. If the file cannot be deleted or is not found,FTPSERVER_NO_FILE
should be returned.
Extending the previous example, the cyg_ftpserver might look like this:
static cyg_ftpserver ftp_server = { .port = 2121, // Listen on port 2121 .root = "/fatfs/ftp", // FTP to/from here .greeting = "Welcome to Fubar FTP service.", // Welcome string .data_port = 40000, // Move data ports to 40000+ .open = example_open, .read = example_read, .write = example_write, .close = example_close, .auth = example_auth, .delete = example_delete, };
Configuration Options
The FTP server package contains a number of configuration options:
-
CYGNUM_NET_FTPSERVER_BUFFER_SIZE
- This option defines the size of the buffer used for data transfers. Buffer size is a tradeoff between memory use and transfer speed. The default should be a reasonable compromise between these two.
-
CYGNUM_NET_FTPSERVER_USER_SIZE
- This option defines the size of the buffer used for storing the user name supplied by the client.
-
CYGNUM_NET_FTPSERVER_PASSWD_SIZE
- This option defines the size of the buffer used for storing the password supplied by the client. The default reflects the habit of using a user's email address as a password for anonymous FTP.
-
CYGNUM_NET_FTPSERVER_CONTROL_TIMEOUT
- This option defines the timeout applied to control streams. If after this number of seconds the client has not interacted with the server, the connection is closed down. Since the server only allows a single client at a time, any client that fails to close a control stream down will block it for others.
-
CYGNUM_NET_FTPSERVER_DATA_TIMEOUT
- This option defines the timeout applied to data streams. If after this number of seconds the client has not transferred data to or from the server, the connection is closed down. Clients are expected to use a data connection immediately after it is created so this timeout can be considerably smaller than the control timeout.
2024-03-18 | eCosPro Non-Commercial Public License |