diff --git a/src/include/gpxe/ftp.h b/src/include/gpxe/ftp.h index 6063abe9..6fad1527 100644 --- a/src/include/gpxe/ftp.h +++ b/src/include/gpxe/ftp.h @@ -8,8 +8,12 @@ */ #include +#include #include +/** FTP default port */ +#define FTP_PORT 21 + /** * FTP states * @@ -45,12 +49,8 @@ struct ftp_request { * remote server. */ void ( *callback ) ( char *data, size_t len ); - /** Completion indicator - * - * This will be set to a non-zero value when the transfer is - * complete. A negative value indicates an error. - */ - int complete; + /** Asynchronous operation for this FTP operation */ + struct async_operation aop; /** Current state */ enum ftp_state state; @@ -69,6 +69,6 @@ struct ftp_request { struct tcp_connection tcp_data; }; -extern void ftp_connect ( struct ftp_request *ftp ); +struct async_operation * ftp_get ( struct ftp_request *ftp ); -#endif +#endif /* _GPXE_FTP_H */ diff --git a/src/include/gpxe/hello.h b/src/include/gpxe/hello.h index a31da3e1..cdd26adf 100644 --- a/src/include/gpxe/hello.h +++ b/src/include/gpxe/hello.h @@ -9,6 +9,7 @@ #include #include +#include enum hello_state { HELLO_SENDING_MESSAGE = 1, @@ -37,10 +38,10 @@ struct hello_request { * remote server. */ void ( *callback ) ( char *data, size_t len ); - /** Connection complete indicator */ - int complete; + /** Asynchronous operation */ + struct async_operation aop; }; -extern void hello_connect ( struct hello_request *hello ); +extern struct async_operation * say_hello ( struct hello_request *hello ); #endif diff --git a/src/net/tcp/ftp.c b/src/net/tcp/ftp.c index b0f9fef9..71a53ccf 100644 --- a/src/net/tcp/ftp.c +++ b/src/net/tcp/ftp.c @@ -4,6 +4,7 @@ #include #include #include +#include #include /** @file @@ -70,13 +71,13 @@ static inline struct ftp_request * tcp_to_ftp ( struct tcp_connection *conn ) { * Mark FTP request as complete * * @v ftp FTP request - * @v complete Completion indicator + * @v rc Return status code * */ -static void ftp_complete ( struct ftp_request *ftp, int complete ) { - ftp->complete = complete; +static void ftp_done ( struct ftp_request *ftp, int rc ) { tcp_close ( &ftp->tcp_data ); tcp_close ( &ftp->tcp ); + async_done ( &ftp->aop, rc ); } /** @@ -145,7 +146,7 @@ static void ftp_reply ( struct ftp_request *ftp ) { err: /* Flag protocol error and close connections */ - ftp_complete ( ftp, -EPROTO ); + ftp_done ( ftp, -EPROTO ); } /** @@ -248,7 +249,7 @@ static void ftp_senddata ( struct tcp_connection *conn, static void ftp_closed ( struct tcp_connection *conn, int status ) { struct ftp_request *ftp = tcp_to_ftp ( conn ); - ftp_complete ( ftp, status ? status : 1 ); + ftp_done ( ftp, status ); } /** FTP control channel operations */ @@ -291,7 +292,7 @@ static void ftp_data_closed ( struct tcp_connection *conn, int status ) { struct ftp_request *ftp = tcp_to_ftp_data ( conn ); if ( status ) - ftp_complete ( ftp, status ); + ftp_done ( ftp, status ); } /** @@ -327,10 +328,11 @@ static struct tcp_operations ftp_data_tcp_operations = { * * @v ftp FTP request */ -void ftp_connect ( struct ftp_request *ftp ) { +struct async_operation * ftp_get ( struct ftp_request *ftp ) { ftp->tcp.tcp_op = &ftp_tcp_operations; ftp->tcp_data.tcp_op = &ftp_data_tcp_operations; ftp->recvbuf = ftp->status_text; ftp->recvsize = sizeof ( ftp->status_text ) - 1; tcp_connect ( &ftp->tcp ); + return &ftp->aop; } diff --git a/src/net/tcp/hello.c b/src/net/tcp/hello.c index baaf8c76..d74e52f9 100644 --- a/src/net/tcp/hello.c +++ b/src/net/tcp/hello.c @@ -2,6 +2,7 @@ #include #include #include +#include #include /** @file @@ -13,7 +14,8 @@ * message (hello_request::message). Any data received from the * server will be passed to the callback function, * hello_request::callback(), and once the connection has been closed, - * hello_request::complete will be set to a non-zero value. + * the asynchronous operation associated with the request will be + * marked as complete. * * To use this code, do something like: * @@ -31,10 +33,7 @@ * hello.sin.sin_addr.s_addr = ... server IP address ... * hello.sin.sin_port = ... server port ... * - * hello_connect ( &hello ); - * while ( ! hello.completed ) { - * run_tcpip(); - * } + * rc = async_wait ( say_hello ( &hello ) ); * * @endcode * @@ -52,7 +51,7 @@ tcp_to_hello ( struct tcp_connection *conn ) { static void hello_closed ( struct tcp_connection *conn, int status ) { struct hello_request *hello = tcp_to_hello ( conn ); - hello->complete = ( status ? status : 1 ); + async_done ( &hello->aop, status ); } static void hello_connected ( struct tcp_connection *conn ) { @@ -92,7 +91,8 @@ static void hello_newdata ( struct tcp_connection *conn, void *data, hello->callback ( data, len ); } -static void hello_senddata ( struct tcp_connection *conn ) { +static void hello_senddata ( struct tcp_connection *conn, + void *buf __unused, size_t len __unused ) { struct hello_request *hello = tcp_to_hello ( conn ); tcp_send ( conn, hello->message, hello->remaining ); @@ -111,7 +111,8 @@ static struct tcp_operations hello_tcp_operations = { * * @v hello "Hello world" request */ -void hello_connect ( struct hello_request *hello ) { +struct async_operation * say_hello ( struct hello_request *hello ) { hello->tcp.tcp_op = &hello_tcp_operations; tcp_connect ( &hello->tcp ); + return &hello->aop; } diff --git a/src/tests/ftptest.c b/src/tests/ftptest.c new file mode 100644 index 00000000..f8208de7 --- /dev/null +++ b/src/tests/ftptest.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include + +static void test_ftp_callback ( char *data, size_t len ) { + unsigned int i; + char c; + + for ( i = 0 ; i < len ; i++ ) { + c = data[i]; + if ( c == '\r' ) { + /* Print nothing */ + } else if ( ( c == '\n' ) || ( c >= 32 ) || ( c <= 126 ) ) { + putchar ( c ); + } else { + putchar ( '.' ); + } + } +} + +void test_ftp ( struct in_addr server, const char *filename ) { + struct ftp_request ftp; + int rc; + + printf ( "FTP fetching %s:%s\n", inet_ntoa ( server ), filename ); + + memset ( &ftp, 0, sizeof ( ftp ) ); + ftp.tcp.sin.sin_addr.s_addr = server.s_addr; + ftp.tcp.sin.sin_port = htons ( FTP_PORT ); + ftp.filename = filename; + ftp.callback = test_ftp_callback; + + rc = async_wait ( ftp_get ( &ftp ) ); + if ( rc ) { + printf ( "FTP fetch failed\n" ); + } +} diff --git a/src/tests/hellotest.c b/src/tests/hellotest.c new file mode 100644 index 00000000..e38856ee --- /dev/null +++ b/src/tests/hellotest.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include + +static void test_hello_callback ( char *data, size_t len ) { + unsigned int i; + char c; + + for ( i = 0 ; i < len ; i++ ) { + c = data[i]; + if ( c == '\r' ) { + /* Print nothing */ + } else if ( ( c == '\n' ) || ( c >= 32 ) || ( c <= 126 ) ) { + putchar ( c ); + } else { + putchar ( '.' ); + } + } +} + +void test_hello ( struct sockaddr_in *server, const char *message ) { + struct hello_request hello; + int rc; + + printf ( "Saying \"%s\" to %s:%d\n", message, + inet_ntoa ( server->sin_addr ), ntohs ( server->sin_port ) ); + + memset ( &hello, 0, sizeof ( hello ) ); + hello.tcp.sin = *server; + hello.message = message; + hello.callback = test_hello_callback; + + rc = async_wait ( say_hello ( &hello ) ); + if ( rc ) { + printf ( "HELLO fetch failed\n" ); + } +}