summaryrefslogtreecommitdiffstats
path: root/src/net/tcp/httpcore.c
diff options
context:
space:
mode:
authorMichael Brown2012-05-22 15:14:35 +0200
committerMichael Brown2012-05-23 00:18:14 +0200
commit8f5d44b5c6b12964e2678739a24f45da1c5d2c11 (patch)
treee3cca65dd7ea6c4ac21ef8ecc177a21ca464c500 /src/net/tcp/httpcore.c
parent[http] Defer processing response code until after receiving all headers (diff)
downloadipxe-8f5d44b5c6b12964e2678739a24f45da1c5d2c11.tar.gz
ipxe-8f5d44b5c6b12964e2678739a24f45da1c5d2c11.tar.xz
ipxe-8f5d44b5c6b12964e2678739a24f45da1c5d2c11.zip
[http] Split construction of Authorization header out of http_step()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/tcp/httpcore.c')
-rw-r--r--src/net/tcp/httpcore.c153
1 files changed, 96 insertions, 57 deletions
diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c
index 27d32bfd..52989514 100644
--- a/src/net/tcp/httpcore.c
+++ b/src/net/tcp/httpcore.c
@@ -731,27 +731,56 @@ static void http_socket_close ( struct http_request *http, int rc ) {
}
/**
- * HTTP process
+ * Generate HTTP Basic authorisation string
*
* @v http HTTP request
+ * @ret auth Authorisation string, or NULL on error
+ *
+ * The authorisation string is dynamically allocated, and must be
+ * freed by the caller.
*/
-static void http_step ( struct http_request *http ) {
- const char *host = http->uri->host;
+static char * http_basic_auth ( struct http_request *http ) {
const char *user = http->uri->user;
const char *password =
( http->uri->password ? http->uri->password : "" );
- size_t user_pw_len = ( user ? ( strlen ( user ) + 1 /* ":" */ +
- strlen ( password ) ) : 0 );
+ size_t user_pw_len =
+ ( strlen ( user ) + 1 /* ":" */ + strlen ( password ) );
+ char user_pw[ user_pw_len + 1 /* NUL */ ];
size_t user_pw_base64_len = base64_encoded_len ( user_pw_len );
- int request_len = unparse_uri ( NULL, 0, http->uri,
- URI_PATH_BIT | URI_QUERY_BIT );
- struct {
- uint8_t user_pw[ user_pw_len + 1 /* NUL */ ];
- char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
- char request[ request_len + 1 /* NUL */ ];
- char range[48]; /* Enough for two 64-bit integers in decimal */
- } *dynamic;
- int partial;
+ char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
+ char *auth;
+ int len;
+
+ /* Sanity check */
+ assert ( user != NULL );
+
+ /* Make "user:password" string from decoded fields */
+ snprintf ( user_pw, sizeof ( user_pw ), "%s:%s", user, password );
+
+ /* Base64-encode the "user:password" string */
+ base64_encode ( ( void * ) user_pw, user_pw_len, user_pw_base64 );
+
+ /* Generate the authorisation string */
+ len = asprintf ( &auth, "Authorization: Basic %s\r\n",
+ user_pw_base64 );
+ if ( len < 0 )
+ return NULL;
+
+ return auth;
+}
+
+/**
+ * HTTP process
+ *
+ * @v http HTTP request
+ */
+static void http_step ( struct http_request *http ) {
+ size_t uri_len;
+ char *method;
+ char *uri;
+ char *range;
+ char *auth;
+ int len;
int rc;
/* Do nothing if we have already transmitted the request */
@@ -762,74 +791,84 @@ static void http_step ( struct http_request *http ) {
if ( ! xfer_window ( &http->socket ) )
return;
- /* Allocate dynamic storage */
- dynamic = malloc ( sizeof ( *dynamic ) );
- if ( ! dynamic ) {
- rc = -ENOMEM;
- goto err_alloc;
+ /* Force a HEAD request if we have nowhere to send any received data */
+ if ( ( xfer_window ( &http->xfer ) == 0 ) &&
+ ( http->rx_buffer == UNULL ) ) {
+ http->flags |= ( HTTP_HEAD_ONLY | HTTP_CLIENT_KEEPALIVE );
}
- /* Construct path?query request */
- unparse_uri ( dynamic->request, sizeof ( dynamic->request ), http->uri,
- URI_PATH_BIT | URI_QUERY_BIT );
+ /* Determine method */
+ method = ( ( http->flags & HTTP_HEAD_ONLY ) ? "HEAD" : "GET" );
- /* Construct authorisation, if applicable */
- if ( user ) {
- /* Make "user:password" string from decoded fields */
- snprintf ( ( ( char * ) dynamic->user_pw ),
- sizeof ( dynamic->user_pw ), "%s:%s",
- user, password );
-
- /* Base64-encode the "user:password" string */
- base64_encode ( dynamic->user_pw, user_pw_len,
- dynamic->user_pw_base64 );
+ /* Construct path?query request */
+ uri_len = ( unparse_uri ( NULL, 0, http->uri,
+ URI_PATH_BIT | URI_QUERY_BIT )
+ + 1 /* possible "/" */ + 1 /* NUL */ );
+ uri = malloc ( uri_len );
+ if ( ! uri ) {
+ rc = -ENOMEM;
+ goto err_uri;
+ }
+ unparse_uri ( uri, uri_len, http->uri, URI_PATH_BIT | URI_QUERY_BIT );
+ if ( ! uri[0] ) {
+ uri[0] = '/';
+ uri[1] = '\0';
}
- /* Force a HEAD request if we have nowhere to send any received data */
- if ( ( xfer_window ( &http->xfer ) == 0 ) &&
- ( http->rx_buffer == UNULL ) ) {
- http->flags |= ( HTTP_HEAD_ONLY | HTTP_CLIENT_KEEPALIVE );
+ /* Calculate range request parameters if applicable */
+ if ( http->partial_len ) {
+ len = asprintf ( &range, "Range: bytes=%zd-%zd\r\n",
+ http->partial_start,
+ ( http->partial_start + http->partial_len
+ - 1 ) );
+ if ( len < 0 ) {
+ rc = len;
+ goto err_range;
+ }
+ } else {
+ range = NULL;
}
- /* Determine type of request */
- partial = ( http->partial_len != 0 );
- snprintf ( dynamic->range, sizeof ( dynamic->range ),
- "%zd-%zd", http->partial_start,
- ( http->partial_start + http->partial_len - 1 ) );
+ /* Construct authorisation, if applicable */
+ if ( http->uri->user ) {
+ auth = http_basic_auth ( http );
+ if ( ! auth ) {
+ rc = -ENOMEM;
+ goto err_auth;
+ }
+ } else {
+ auth = NULL;
+ }
/* Mark request as transmitted */
http->flags &= ~HTTP_TX_PENDING;
- /* Send GET request */
+ /* Send request */
if ( ( rc = xfer_printf ( &http->socket,
- "%s %s%s HTTP/1.1\r\n"
+ "%s %s HTTP/1.1\r\n"
"User-Agent: iPXE/" VERSION "\r\n"
"Host: %s%s%s\r\n"
- "%s%s%s%s%s%s%s"
+ "%s%s%s"
"\r\n",
- ( ( http->flags & HTTP_HEAD_ONLY ) ?
- "HEAD" : "GET" ),
- ( http->uri->path ? "" : "/" ),
- dynamic->request, host,
+ method, uri, http->uri->host,
( http->uri->port ?
":" : "" ),
( http->uri->port ?
http->uri->port : "" ),
( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ?
"Connection: keep-alive\r\n" : "" ),
- ( partial ? "Range: bytes=" : "" ),
- ( partial ? dynamic->range : "" ),
- ( partial ? "\r\n" : "" ),
- ( user ?
- "Authorization: Basic " : "" ),
- ( user ? dynamic->user_pw_base64 : "" ),
- ( user ? "\r\n" : "" ) ) ) != 0 ) {
+ ( range ? range : "" ),
+ ( auth ? auth : "" ) ) ) != 0 ) {
goto err_xfer;
}
err_xfer:
- free ( dynamic );
- err_alloc:
+ free ( auth );
+ err_auth:
+ free ( range );
+ err_range:
+ free ( uri );
+ err_uri:
if ( rc != 0 )
http_close ( http, rc );
}