mirror of
https://github.com/ipxe/ipxe
synced 2025-12-14 07:50:43 +03:00
Change FTP to use a data buffer rather than a callback function.
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
|
||||||
|
|||||||
@@ -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 );
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user