Module to implement the protocol part of the client side of the
File Transfer Protocol, RFC 959.
Responsible only for parsing and generating bytes on the FTP control
connection. Doesn't actually do any networking calls; that is left to the
bfb_pipe module. This separation of duties makes writing self-test code
easier.
When the caller requests a file transfer or directory listing and
doesn't specify a local port number, this code will issue PASV, and
getStatus() will indicate an address.
The caller should connect to that address immediately, and begin using
that connection for the file or directory transfer.
Example:
After calling the login method, calling getOutput() will return a buffer
containing 'USER username\r\n' to be sent to the server. When the result line
comes back from the server, it should be passed to the giveInput method.
Calling getOutput() at that point will return a buffer containing
'PASS password\r\n' to be sent to the server, etc.
The success or failure of the login call is then available by calling
getStatus().
- bool isOutputReady()
-
Returns whether getOutput would have a line of output for us.
- bool isPortReady(struct sockaddr_in* address)
-
If a GET, PUT, or LS is in progress, and the server needs to tell us
the port number to connect to, this will return TRUE and give us the
address and port.
i.e. if the server sends status 227, the result of the PASV command is
parsed into the given struct sockaddr_in *, and the caller should
arrange to transfer data.
- bool isQuit()
-
Returns whether QUIT command has finished.
This should trigger a disconnect.
- int giveInput(const char* ibuf)
-
Offer a null-terminated input line from the server to this session.
Returns 0 if accepted, Unix error code otherwise.
In particular, returns EWOULDBLOCK if not ready for the input.
- const char* getOutput(int* plen = 0)
-
Get the current null-terminated output line to the server
and its length in bytes.
The line is terminated by CR LF and a NUL; the length includes
the CR LF but not the NUL.
You may call it as many times as you like; it will return the
same data. This lets you retry a send.
After the send succeeds, call advanceOutput() to advance to the next
line of output.
Returns NULL if no output is ready yet.
- int advanceOutput()
-
Advances to next line of output; then call getOutput() to get it.
Returns 0 on success, Unix error code on error.
In particular, returns EWOULDBLOCK if no more output is ready.
- void init()
-
Set up the initial state of this protocol session.
- int getStatus(char* buf, size_t buflen)
-
Get the status of the last login, quit, cd, ls, or get call.
If the operation is still in progress, returns 0.
If the operation has succeeded, returns a value between 200 and 299.
ASCII version of result is returned in given buffer, if buf != NULL.
- int login(const char* username, const char* password)
-
Log in to the server.
Call getStatus() periodically until it returns nonzero to get whether
this command succeeded.
- int quit()
-
Log out from the server. This triggers the QUIT command.
Call getStatus() periodically until it returns nonzero to get whether
this command succeeded.
- int cd(const char* dir)
-
Change directories.
If dir is "..", the CDUP command is used instead of CD.
Call getStatus() periodically until it returns nonzero to get whether
this command succeeded.
- int size(const char* fname)
-
Retrieve file size.
Call getStatus() periodically until it returns nonzero to get whether
this command succeeded, then parse the results out of the status
buffer.
- int type(const char* ttype)
-
Set the transfer type.
Call getStatus() periodically until it returns nonzero to get whether
this command succeeded, then parse the results out of the status
buffer.
- int ls(const char* dirname, struct sockaddr_in* address)
-
List the given directory's contents. dirname may be NULL.
Result comes back on a data channel.
Call getStatus() periodically until it returns nonzero to get whether
this command succeeded.
If address is 0, PASV mode is used, and isPortReady() should be called
periodically until it returns true and indicates where to connect to
to retrieve the directory listing.
After retrieving the data from that address, continue calling
getStatus() to get the success status message.
If address is nonzero, PORT mode is used; it is assumed that a
port is already listening on the given address for a connection.
- int get(const char* fname, struct sockaddr_in* address)
-
Retrieve the given file's contents. Result comes back on a data
channel.
Call getStatus() periodically until it returns nonzero to get whether
this command succeeded.
If address is NULL, PASV mode is used, and isPortReady() should be called
periodically until it returns true and indicates where to connect to
to retrieve the file.
After retrieving the data from that address, continue calling
getStatus() to get the success status message.
If address is not NULL, PORT mode is used; it is assumed that a
port is already listening on the given address for a connection.