summaryrefslogtreecommitdiffstats
path: root/src/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/net')
-rw-r--r--src/net/aoe.c12
-rw-r--r--src/net/tcp/ftp.c4
-rw-r--r--src/net/tcp/hello.c6
-rw-r--r--src/net/tcp/http.c84
-rw-r--r--src/net/tcp/iscsi.c16
-rw-r--r--src/net/udp/dhcp.c17
-rw-r--r--src/net/udp/tftp.c6
7 files changed, 107 insertions, 38 deletions
diff --git a/src/net/aoe.c b/src/net/aoe.c
index 2dc5ed406..1c3cd1d2b 100644
--- a/src/net/aoe.c
+++ b/src/net/aoe.c
@@ -56,7 +56,7 @@ static void aoe_done ( struct aoe_session *aoe, int rc ) {
aoe->command = NULL;
/* Mark async operation as complete */
- async_done ( &aoe->aop, rc );
+ async_done ( &aoe->async, rc );
}
/**
@@ -309,17 +309,19 @@ void aoe_close ( struct aoe_session *aoe ) {
*
* @v aoe AoE session
* @v command ATA command
- * @ret aop Asynchronous operation
+ * @v parent Parent asynchronous operation
+ * @ret rc Return status code
*
* Only one command may be issued concurrently per session. This call
* is non-blocking; use async_wait() to wait for the command to
* complete.
*/
-struct async_operation * aoe_issue ( struct aoe_session *aoe,
- struct ata_command *command ) {
+int aoe_issue ( struct aoe_session *aoe, struct ata_command *command,
+ struct async *parent ) {
aoe->command = command;
aoe->status = 0;
aoe->command_offset = 0;
aoe_send_command ( aoe );
- return &aoe->aop;
+ async_init ( &aoe->async, &default_async_operations, parent );
+ return 0;
}
diff --git a/src/net/tcp/ftp.c b/src/net/tcp/ftp.c
index a857f7b7b..8a27f8cb6 100644
--- a/src/net/tcp/ftp.c
+++ b/src/net/tcp/ftp.c
@@ -83,7 +83,7 @@ static void ftp_done ( struct ftp_request *ftp, int rc ) {
tcp_close ( &ftp->tcp_data );
/* Mark asynchronous operation as complete */
- async_done ( &ftp->aop, rc );
+ async_done ( &ftp->async, rc );
}
/**
@@ -379,5 +379,5 @@ struct async_operation * ftp_get ( struct ftp_request *ftp ) {
if ( ( rc = tcp_connect ( &ftp->tcp, &ftp->server, 0 ) ) != 0 )
ftp_done ( ftp, rc );
- return &ftp->aop;
+ return &ftp->async;
}
diff --git a/src/net/tcp/hello.c b/src/net/tcp/hello.c
index 4de7e8729..25c079369 100644
--- a/src/net/tcp/hello.c
+++ b/src/net/tcp/hello.c
@@ -51,7 +51,7 @@ tcp_to_hello ( struct tcp_application *app ) {
static void hello_closed ( struct tcp_application *app, int status ) {
struct hello_request *hello = tcp_to_hello ( app );
- async_done ( &hello->aop, status );
+ async_done ( &hello->async, status );
}
static void hello_connected ( struct tcp_application *app ) {
@@ -116,7 +116,7 @@ struct async_operation * say_hello ( struct hello_request *hello ) {
hello->tcp.tcp_op = &hello_tcp_operations;
if ( ( rc = tcp_connect ( &hello->tcp, &hello->server, 0 ) ) != 0 )
- async_done ( &hello->aop, rc );
+ async_done ( &hello->async, rc );
- return &hello->aop;
+ return &hello->async;
}
diff --git a/src/net/tcp/http.c b/src/net/tcp/http.c
index 22e24082e..dfa39f537 100644
--- a/src/net/tcp/http.c
+++ b/src/net/tcp/http.c
@@ -27,9 +27,11 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
-#include <vsprintf.h>
+#include <errno.h>
#include <assert.h>
+#include <vsprintf.h>
#include <gpxe/async.h>
+#include <gpxe/uri.h>
#include <gpxe/buffer.h>
#include <gpxe/http.h>
@@ -67,7 +69,7 @@ static void http_done ( struct http_request *http, int rc ) {
}
/* Mark async operation as complete */
- async_done ( &http->aop, rc );
+ async_done ( &http->async, rc );
}
/**
@@ -303,12 +305,21 @@ static void http_newdata ( struct tcp_application *app,
static void http_senddata ( struct tcp_application *app,
void *buf, size_t len ) {
struct http_request *http = tcp_to_http ( app );
+ const char *path = http->uri->path;
+ const char *host = http->uri->host;
+
+ if ( ! path )
+ path = "/";
+
+ if ( ! host )
+ host = "";
len = snprintf ( buf, len,
- "GET /%s HTTP/1.1\r\n"
+ "GET %s HTTP/1.1\r\n"
"User-Agent: gPXE/" VERSION "\r\n"
"Host: %s\r\n"
- "\r\n", http->filename, http->hostname );
+ "\r\n", path, host );
+
tcp_send ( app, ( buf + http->tx_offset ), ( len - http->tx_offset ) );
}
@@ -347,16 +358,71 @@ static struct tcp_operations http_tcp_operations = {
};
/**
+ * Reap asynchronous operation
+ *
+ * @v async Asynchronous operation
+ */
+static void http_reap ( struct async *async ) {
+ struct http_request *http =
+ container_of ( async, struct http_request, async );
+
+ free_uri ( http->uri );
+ free ( http );
+}
+
+/** HTTP asynchronous operations */
+static struct async_operations http_async_operations = {
+ .reap = http_reap,
+};
+
+#warning "Quick name resolution hack"
+#include <byteswap.h>
+
+/**
* Initiate a HTTP connection
*
- * @v http a HTTP request
+ * @v uri Uniform Resource Identifier
+ * @v buffer Buffer into which to download file
+ * @v parent Parent asynchronous operation
+ * @ret rc Return status code
+ *
+ * If it returns success, this function takes ownership of the URI.
*/
-struct async_operation * http_get ( struct http_request *http ) {
+int http_get ( struct uri *uri, struct buffer *buffer, struct async *parent ) {
+ struct http_request *http;
int rc;
+ /* Allocate and populate HTTP structure */
+ http = malloc ( sizeof ( *http ) );
+ if ( ! http ) {
+ rc = -ENOMEM;
+ goto err;
+ }
+ memset ( http, 0, sizeof ( *http ) );
+ http->uri = uri;
+ http->buffer = buffer;
http->tcp.tcp_op = &http_tcp_operations;
- if ( ( rc = tcp_connect ( &http->tcp, &http->server, 0 ) ) != 0 )
- async_done ( &http->aop, rc );
- return &http->aop;
+#warning "Quick name resolution hack"
+ union {
+ struct sockaddr_tcpip st;
+ struct sockaddr_in sin;
+ } server;
+ server.sin.sin_port = htons ( HTTP_PORT );
+ server.sin.sin_family = AF_INET;
+ if ( inet_aton ( uri->host, &server.sin.sin_addr ) == 0 ) {
+ rc = -EINVAL;
+ goto err;
+ }
+
+ if ( ( rc = tcp_connect ( &http->tcp, &server.st, 0 ) ) != 0 )
+ goto err;
+
+ async_init ( &http->async, &http_async_operations, parent );
+ return 0;
+
+ err:
+ DBGC ( http, "HTTP %p could not create request: %s\n",
+ http, strerror ( rc ) );
+ return rc;
}
diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c
index ae23cfe8e..09edf697d 100644
--- a/src/net/tcp/iscsi.c
+++ b/src/net/tcp/iscsi.c
@@ -121,7 +121,7 @@ static void iscsi_done ( struct iscsi_session *iscsi, int rc ) {
iscsi->command = NULL;
/* Mark asynchronous operation as complete */
- async_done ( &iscsi->aop, rc );
+ async_done ( &iscsi->async, rc );
}
/****************************************************************************
@@ -1208,10 +1208,11 @@ static struct tcp_operations iscsi_tcp_operations = {
*
* @v iscsi iSCSI session
* @v command SCSI command
- * @ret aop Asynchronous operation for this SCSI command
+ * @v parent Parent asynchronous operation
+ * @ret rc Return status code
*/
-struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
- struct scsi_command *command ) {
+int iscsi_issue ( struct iscsi_session *iscsi, struct scsi_command *command,
+ struct async *parent ) {
int rc;
assert ( iscsi->command == NULL );
@@ -1219,7 +1220,7 @@ struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
if ( iscsi->instant_rc ) {
/* Abort immediately rather than retrying */
- iscsi_done ( iscsi, iscsi->instant_rc );
+ return iscsi->instant_rc;
} else if ( iscsi->status ) {
/* Session already open: issue command */
iscsi_start_command ( iscsi );
@@ -1231,11 +1232,12 @@ struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
0 ) ) != 0 ) {
DBGC ( iscsi, "iSCSI %p could not open TCP "
"connection: %s\n", iscsi, strerror ( rc ) );
- iscsi_done ( iscsi, rc );
+ return rc;
}
}
- return &iscsi->aop;
+ async_init ( &iscsi->async, &default_async_operations, parent );
+ return 0;
}
/**
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index 8f8297018..a2d3db6bb 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -517,7 +517,7 @@ static void dhcp_done ( struct dhcp_session *dhcp, int rc ) {
ref_del ( &dhcp->netdev_ref );
/* Mark async operation as complete */
- async_done ( &dhcp->aop, rc );
+ async_done ( &dhcp->async, rc );
}
/** Address for transmitting DHCP requests */
@@ -713,14 +713,15 @@ static void dhcp_forget_netdev ( struct reference *ref ) {
* Initiate DHCP on a network interface
*
* @v dhcp DHCP session
- * @ret aop Asynchronous operation
+ * @v parent Parent asynchronous operation
+ * @ret rc Return status code
*
* If the DHCP operation completes successfully, the
* dhcp_session::options field will be filled in with the resulting
* options block. The caller takes responsibility for eventually
* calling free_dhcp_options().
*/
-struct async_operation * start_dhcp ( struct dhcp_session *dhcp ) {
+int start_dhcp ( struct dhcp_session *dhcp, struct async *parent ) {
int rc;
/* Initialise DHCP session */
@@ -729,10 +730,8 @@ struct async_operation * start_dhcp ( struct dhcp_session *dhcp ) {
dhcp->state = DHCPDISCOVER;
/* Bind to local port */
- if ( ( rc = udp_open ( &dhcp->udp, htons ( BOOTPC_PORT ) ) ) != 0 ) {
- async_done ( &dhcp->aop, rc );
- goto out;
- }
+ if ( ( rc = udp_open ( &dhcp->udp, htons ( BOOTPC_PORT ) ) ) != 0 )
+ return rc;
/* Add persistent reference to net device */
dhcp->netdev_ref.forget = dhcp_forget_netdev;
@@ -741,6 +740,6 @@ struct async_operation * start_dhcp ( struct dhcp_session *dhcp ) {
/* Proof of concept: just send a single DHCPDISCOVER */
dhcp_send_request ( dhcp );
- out:
- return &dhcp->aop;
+ async_init ( &dhcp->async, &default_async_operations, parent );
+ return 0;
}
diff --git a/src/net/udp/tftp.c b/src/net/udp/tftp.c
index 6753e8380..69650ab0f 100644
--- a/src/net/udp/tftp.c
+++ b/src/net/udp/tftp.c
@@ -142,7 +142,7 @@ static void tftp_done ( struct tftp_session *tftp, int rc ) {
udp_close ( &tftp->udp );
/* Mark async operation as complete */
- async_done ( &tftp->aop, rc );
+ async_done ( &tftp->async, rc );
}
/**
@@ -477,7 +477,7 @@ struct async_operation * tftp_get ( struct tftp_session *tftp ) {
/* Open UDP connection */
if ( ( rc = udp_open ( &tftp->udp, 0 ) ) != 0 ) {
- async_done ( &tftp->aop, rc );
+ async_done ( &tftp->async, rc );
goto out;
}
@@ -485,5 +485,5 @@ struct async_operation * tftp_get ( struct tftp_session *tftp ) {
tftp_send_packet ( tftp );
out:
- return &tftp->aop;
+ return &tftp->async;
}