Change FTP to use a data buffer rather than a callback function.
authorMichael Brown <mcb30@etherboot.org>
Thu, 11 Jan 2007 04:51:20 +0000 (04:51 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 11 Jan 2007 04:51:20 +0000 (04:51 +0000)
src/include/gpxe/ftp.h
src/net/tcp/ftp.c
src/tests/ftptest.c

index c3eafb6..e296021 100644 (file)
@@ -11,6 +11,8 @@
 #include <gpxe/async.h>
 #include <gpxe/tcp.h>
 
+struct buffer;
+
 /** FTP default port */
 #define FTP_PORT 21
 
@@ -40,15 +42,8 @@ struct ftp_request {
        struct sockaddr_tcpip server;
        /** File to download */
        const char *filename;
-       /** Callback function
-        *
-        * @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 );
+       /** Data buffer to fill */
+       struct buffer *buffer;
 
        /** Current state */
        enum ftp_state state;
@@ -62,6 +57,8 @@ struct ftp_request {
        char status_text[4];
        /** Passive-mode parameters, as text */
        char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
+       /** Amount of data received */
+       size_t data_rcvd;
 
        /** TCP application for the control channel */
        struct tcp_application tcp;
index e345a65..ef5423a 100644 (file)
@@ -5,6 +5,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <gpxe/async.h>
+#include <gpxe/buffer.h>
 #include <gpxe/ftp.h>
 
 /** @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
  * 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 );
 
-       DBGC ( ftp, "FTP %p control connection closed (status %d)\n",
-              ftp, status );
+       DBGC ( ftp, "FTP %p control connection closed: %s\n",
+              ftp, strerror ( rc ) );
 
        /* Complete FTP operation */
-       ftp_done ( ftp, status );
+       ftp_done ( ftp, rc );
 }
 
 /** 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.
  */
-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 );
 
-       DBGC ( ftp, "FTP %p data connection closed (status %d)\n",
-              ftp, status );
+       DBGC ( ftp, "FTP %p data connection closed: %s\n",
+              ftp, strerror ( rc ) );
        
        /* If there was an error, close control channel and record status */
-       if ( status )
-               ftp_done ( ftp, status );
+       if ( rc )
+               ftp_done ( ftp, rc );
 }
 
 /**
@@ -331,14 +332,23 @@ static void ftp_data_closed ( struct tcp_application *app, int status ) {
  * @v app      TCP application
  * @v data     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,
                               void *data, size_t len ) {
        struct ftp_request *ftp = tcp_to_ftp_data ( app );
+       int rc;
+
+       /* 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;
+       }
 
-       ftp->callback ( data, len );
+       /* Update received data total */
+       ftp->data_rcvd += len;
 }
 
 /** 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 );
 
-       ftp->tcp.tcp_op = &ftp_tcp_operations;
-       ftp->tcp_data.tcp_op = &ftp_data_tcp_operations;
+       ftp->state = FTP_CONNECT;
+       ftp->already_sent = 0;
        ftp->recvbuf = ftp->status_text;
        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 )
                ftp_done ( ftp, rc );
 
index c4795c0..d7208f9 100644 (file)
@@ -4,9 +4,10 @@
 #include <console.h>
 #include <vsprintf.h>
 #include <gpxe/async.h>
+#include <gpxe/buffer.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;
        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 ) {
+       char data[256];
+       struct buffer buffer;
        struct ftp_request ftp;
        int rc;
 
        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 ) );
        memcpy ( &ftp.server, server, sizeof ( ftp.server ) );
        ftp.filename = filename;
-       ftp.callback = test_ftp_callback;
+       ftp.buffer = &buffer;
 
        rc = async_wait ( ftp_get ( &ftp ) );
        if ( rc ) {
                printf ( "FTP fetch failed\n" );
+               return;
        }
+
+       printf ( "FTP received %d bytes\n", buffer.fill );
+
+       print_ftp_response ( data, buffer.fill );
 }