Change FTP to use a data buffer rather than a callback function.

This commit is contained in:
Michael Brown
2007-01-11 04:51:20 +00:00
parent c0ef730ec4
commit 6918cf9e9e
3 changed files with 47 additions and 25 deletions

View File

@@ -11,6 +11,8 @@
#include <gpxe/async.h> #include <gpxe/async.h>
#include <gpxe/tcp.h> #include <gpxe/tcp.h>
struct buffer;
/** FTP default port */ /** FTP default port */
#define FTP_PORT 21 #define FTP_PORT 21
@@ -40,15 +42,8 @@ struct ftp_request {
struct sockaddr_tcpip server; struct sockaddr_tcpip server;
/** File to download */ /** File to download */
const char *filename; const char *filename;
/** Callback function /** Data buffer to fill */
* struct buffer *buffer;
* @v data Received data
* @v len Length of received data
*
* This function is called for all data received from the
* remote server.
*/
void ( *callback ) ( char *data, size_t len );
/** Current state */ /** Current state */
enum ftp_state state; enum ftp_state state;
@@ -62,6 +57,8 @@ struct ftp_request {
char status_text[4]; char status_text[4];
/** Passive-mode parameters, as text */ /** Passive-mode parameters, as text */
char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */ char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
/** Amount of data received */
size_t data_rcvd;
/** TCP application for the control channel */ /** TCP application for the control channel */
struct tcp_application tcp; struct tcp_application tcp;

View File

@@ -5,6 +5,7 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <gpxe/async.h> #include <gpxe/async.h>
#include <gpxe/buffer.h>
#include <gpxe/ftp.h> #include <gpxe/ftp.h>
/** @file /** @file
@@ -268,14 +269,14 @@ static void ftp_senddata ( struct tcp_application *app,
* When the control channel is closed, the data channel must also be * When the control channel is closed, the data channel must also be
* closed, if it is currently open. * closed, if it is currently open.
*/ */
static void ftp_closed ( struct tcp_application *app, int status ) { static void ftp_closed ( struct tcp_application *app, int rc ) {
struct ftp_request *ftp = tcp_to_ftp ( app ); struct ftp_request *ftp = tcp_to_ftp ( app );
DBGC ( ftp, "FTP %p control connection closed (status %d)\n", DBGC ( ftp, "FTP %p control connection closed: %s\n",
ftp, status ); ftp, strerror ( rc ) );
/* Complete FTP operation */ /* Complete FTP operation */
ftp_done ( ftp, status ); ftp_done ( ftp, rc );
} }
/** FTP control channel operations */ /** FTP control channel operations */
@@ -314,15 +315,15 @@ tcp_to_ftp_data ( struct tcp_application *app ) {
* *
* If the data channel is closed due to an error, we abort the request. * If the data channel is closed due to an error, we abort the request.
*/ */
static void ftp_data_closed ( struct tcp_application *app, int status ) { static void ftp_data_closed ( struct tcp_application *app, int rc ) {
struct ftp_request *ftp = tcp_to_ftp_data ( app ); struct ftp_request *ftp = tcp_to_ftp_data ( app );
DBGC ( ftp, "FTP %p data connection closed (status %d)\n", DBGC ( ftp, "FTP %p data connection closed: %s\n",
ftp, status ); ftp, strerror ( rc ) );
/* If there was an error, close control channel and record status */ /* If there was an error, close control channel and record status */
if ( status ) if ( rc )
ftp_done ( ftp, status ); ftp_done ( ftp, rc );
} }
/** /**
@@ -331,14 +332,23 @@ static void ftp_data_closed ( struct tcp_application *app, int status ) {
* @v app TCP application * @v app TCP application
* @v data New data * @v data New data
* @v len Length of new data * @v len Length of new data
*
* Data is handed off to the callback registered in the FTP request.
*/ */
static void ftp_data_newdata ( struct tcp_application *app, static void ftp_data_newdata ( struct tcp_application *app,
void *data, size_t len ) { void *data, size_t len ) {
struct ftp_request *ftp = tcp_to_ftp_data ( app ); struct ftp_request *ftp = tcp_to_ftp_data ( app );
int rc;
ftp->callback ( data, len ); /* Fill data buffer */
if ( ( rc = fill_buffer ( ftp->buffer, data,
ftp->data_rcvd, len ) ) != 0 ){
DBGC ( ftp, "FTP %p failed to fill data buffer: %s\n",
ftp, strerror ( rc ) );
ftp_done ( ftp, rc );
return;
}
/* Update received data total */
ftp->data_rcvd += len;
} }
/** FTP data channel operations */ /** FTP data channel operations */
@@ -363,10 +373,13 @@ struct async_operation * ftp_get ( struct ftp_request *ftp ) {
DBGC ( ftp, "FTP %p fetching %s\n", ftp, ftp->filename ); DBGC ( ftp, "FTP %p fetching %s\n", ftp, ftp->filename );
ftp->tcp.tcp_op = &ftp_tcp_operations; ftp->state = FTP_CONNECT;
ftp->tcp_data.tcp_op = &ftp_data_tcp_operations; ftp->already_sent = 0;
ftp->recvbuf = ftp->status_text; ftp->recvbuf = ftp->status_text;
ftp->recvsize = sizeof ( ftp->status_text ) - 1; ftp->recvsize = sizeof ( ftp->status_text ) - 1;
ftp->data_rcvd = 0;
ftp->tcp.tcp_op = &ftp_tcp_operations;
ftp->tcp_data.tcp_op = &ftp_data_tcp_operations;
if ( ( rc = tcp_connect ( &ftp->tcp, &ftp->server, 0 ) ) != 0 ) if ( ( rc = tcp_connect ( &ftp->tcp, &ftp->server, 0 ) ) != 0 )
ftp_done ( ftp, rc ); ftp_done ( ftp, rc );

View File

@@ -4,9 +4,10 @@
#include <console.h> #include <console.h>
#include <vsprintf.h> #include <vsprintf.h>
#include <gpxe/async.h> #include <gpxe/async.h>
#include <gpxe/buffer.h>
#include <gpxe/ftp.h> #include <gpxe/ftp.h>
static void test_ftp_callback ( char *data, size_t len ) { static void print_ftp_response ( char *data, size_t len ) {
unsigned int i; unsigned int i;
char c; char c;
@@ -23,18 +24,29 @@ static void test_ftp_callback ( char *data, size_t len ) {
} }
void test_ftp ( struct sockaddr_tcpip *server, const char *filename ) { void test_ftp ( struct sockaddr_tcpip *server, const char *filename ) {
char data[256];
struct buffer buffer;
struct ftp_request ftp; struct ftp_request ftp;
int rc; int rc;
printf ( "FTP fetching %s\n", filename ); printf ( "FTP fetching %s\n", filename );
memset ( &buffer, 0, sizeof ( buffer ) );
buffer.addr = virt_to_phys ( data );
buffer.len = sizeof ( data );
memset ( &ftp, 0, sizeof ( ftp ) ); memset ( &ftp, 0, sizeof ( ftp ) );
memcpy ( &ftp.server, server, sizeof ( ftp.server ) ); memcpy ( &ftp.server, server, sizeof ( ftp.server ) );
ftp.filename = filename; ftp.filename = filename;
ftp.callback = test_ftp_callback; ftp.buffer = &buffer;
rc = async_wait ( ftp_get ( &ftp ) ); rc = async_wait ( ftp_get ( &ftp ) );
if ( rc ) { if ( rc ) {
printf ( "FTP fetch failed\n" ); printf ( "FTP fetch failed\n" );
return;
} }
printf ( "FTP received %d bytes\n", buffer.fill );
print_ftp_response ( data, buffer.fill );
} }