iPXE
httpcore.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 /**
00027  * @file
00028  *
00029  * Hyper Text Transfer Protocol (HTTP) core functionality
00030  *
00031  */
00032 
00033 #include <stdint.h>
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <string.h>
00037 #include <strings.h>
00038 #include <byteswap.h>
00039 #include <errno.h>
00040 #include <ctype.h>
00041 #include <assert.h>
00042 #include <ipxe/uri.h>
00043 #include <ipxe/refcnt.h>
00044 #include <ipxe/iobuf.h>
00045 #include <ipxe/xfer.h>
00046 #include <ipxe/open.h>
00047 #include <ipxe/process.h>
00048 #include <ipxe/retry.h>
00049 #include <ipxe/timer.h>
00050 #include <ipxe/linebuf.h>
00051 #include <ipxe/xferbuf.h>
00052 #include <ipxe/blockdev.h>
00053 #include <ipxe/acpi.h>
00054 #include <ipxe/version.h>
00055 #include <ipxe/params.h>
00056 #include <ipxe/profile.h>
00057 #include <ipxe/vsprintf.h>
00058 #include <ipxe/errortab.h>
00059 #include <ipxe/http.h>
00060 
00061 /* Disambiguate the various error causes */
00062 #define EACCES_401 __einfo_error ( EINFO_EACCES_401 )
00063 #define EINFO_EACCES_401 \
00064         __einfo_uniqify ( EINFO_EACCES, 0x01, "HTTP 401 Unauthorized" )
00065 #define EINVAL_STATUS __einfo_error ( EINFO_EINVAL_STATUS )
00066 #define EINFO_EINVAL_STATUS \
00067         __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid status line" )
00068 #define EINVAL_HEADER __einfo_error ( EINFO_EINVAL_HEADER )
00069 #define EINFO_EINVAL_HEADER \
00070         __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid header" )
00071 #define EINVAL_CONTENT_LENGTH __einfo_error ( EINFO_EINVAL_CONTENT_LENGTH )
00072 #define EINFO_EINVAL_CONTENT_LENGTH \
00073         __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid content length" )
00074 #define EINVAL_CHUNK_LENGTH __einfo_error ( EINFO_EINVAL_CHUNK_LENGTH )
00075 #define EINFO_EINVAL_CHUNK_LENGTH \
00076         __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid chunk length" )
00077 #define EIO_OTHER __einfo_error ( EINFO_EIO_OTHER )
00078 #define EINFO_EIO_OTHER \
00079         __einfo_uniqify ( EINFO_EIO, 0x01, "Unrecognised HTTP response code" )
00080 #define EIO_CONTENT_LENGTH __einfo_error ( EINFO_EIO_CONTENT_LENGTH )
00081 #define EINFO_EIO_CONTENT_LENGTH \
00082         __einfo_uniqify ( EINFO_EIO, 0x02, "Content length mismatch" )
00083 #define EIO_4XX __einfo_error ( EINFO_EIO_4XX )
00084 #define EINFO_EIO_4XX \
00085         __einfo_uniqify ( EINFO_EIO, 0x04, "HTTP 4xx Client Error" )
00086 #define EIO_5XX __einfo_error ( EINFO_EIO_5XX )
00087 #define EINFO_EIO_5XX \
00088         __einfo_uniqify ( EINFO_EIO, 0x05, "HTTP 5xx Server Error" )
00089 #define ENOENT_404 __einfo_error ( EINFO_ENOENT_404 )
00090 #define EINFO_ENOENT_404 \
00091         __einfo_uniqify ( EINFO_ENOENT, 0x01, "HTTP 404 Not Found" )
00092 #define ENOTSUP_CONNECTION __einfo_error ( EINFO_ENOTSUP_CONNECTION )
00093 #define EINFO_ENOTSUP_CONNECTION \
00094         __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported connection header" )
00095 #define ENOTSUP_TRANSFER __einfo_error ( EINFO_ENOTSUP_TRANSFER )
00096 #define EINFO_ENOTSUP_TRANSFER \
00097         __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported transfer encoding" )
00098 #define EPERM_403 __einfo_error ( EINFO_EPERM_403 )
00099 #define EINFO_EPERM_403 \
00100         __einfo_uniqify ( EINFO_EPERM, 0x01, "HTTP 403 Forbidden" )
00101 #define EPROTO_UNSOLICITED __einfo_error ( EINFO_EPROTO_UNSOLICITED )
00102 #define EINFO_EPROTO_UNSOLICITED \
00103         __einfo_uniqify ( EINFO_EPROTO, 0x01, "Unsolicited data" )
00104 
00105 /** Retry delay used when we cannot understand the Retry-After header */
00106 #define HTTP_RETRY_SECONDS 5
00107 
00108 /** Receive profiler */
00109 static struct profiler http_rx_profiler __profiler = { .name = "http.rx" };
00110 
00111 /** Data transfer profiler */
00112 static struct profiler http_xfer_profiler __profiler = { .name = "http.xfer" };
00113 
00114 /** Human-readable error messages */
00115 struct errortab http_errors[] __errortab = {
00116         __einfo_errortab ( EINFO_EIO_4XX ),
00117         __einfo_errortab ( EINFO_EIO_5XX ),
00118 };
00119 
00120 static struct http_state http_request;
00121 static struct http_state http_headers;
00122 static struct http_state http_trailers;
00123 static struct http_transfer_encoding http_transfer_identity;
00124 
00125 /******************************************************************************
00126  *
00127  * Methods
00128  *
00129  ******************************************************************************
00130  */
00131 
00132 /** HTTP HEAD method */
00133 struct http_method http_head = {
00134         .name = "HEAD",
00135 };
00136 
00137 /** HTTP GET method */
00138 struct http_method http_get = {
00139         .name = "GET",
00140 };
00141 
00142 /** HTTP POST method */
00143 struct http_method http_post = {
00144         .name = "POST",
00145 };
00146 
00147 /******************************************************************************
00148  *
00149  * Utility functions
00150  *
00151  ******************************************************************************
00152  */
00153 
00154 /**
00155  * Handle received HTTP line-buffered data
00156  *
00157  * @v http              HTTP transaction
00158  * @v iobuf             I/O buffer
00159  * @v linebuf           Line buffer
00160  * @ret rc              Return status code
00161  */
00162 static int http_rx_linebuf ( struct http_transaction *http,
00163                              struct io_buffer *iobuf,
00164                              struct line_buffer *linebuf ) {
00165         int consumed;
00166         int rc;
00167 
00168         /* Buffer received line */
00169         consumed = line_buffer ( linebuf, iobuf->data, iob_len ( iobuf ) );
00170         if ( consumed < 0 ) {
00171                 rc = consumed;
00172                 DBGC ( http, "HTTP %p could not buffer line: %s\n",
00173                        http, strerror ( rc ) );
00174                 return rc;
00175         }
00176 
00177         /* Consume line */
00178         iob_pull ( iobuf, consumed );
00179 
00180         return 0;
00181 }
00182 
00183 /**
00184  * Get HTTP response token
00185  *
00186  * @v line              Line position
00187  * @v value             Token value to fill in (if any)
00188  * @ret token           Token, or NULL
00189  */
00190 char * http_token ( char **line, char **value ) {
00191         char *token;
00192         char quote = '\0';
00193         char c;
00194 
00195         /* Avoid returning uninitialised data */
00196         if ( value )
00197                 *value = NULL;
00198 
00199         /* Skip any initial whitespace or commas */
00200         while ( ( isspace ( **line ) ) || ( **line == ',' ) )
00201                 (*line)++;
00202 
00203         /* Check for end of line and record token position */
00204         if ( ! **line )
00205                 return NULL;
00206         token = *line;
00207 
00208         /* Scan for end of token */
00209         while ( ( c = **line ) ) {
00210 
00211                 /* Terminate if we hit an unquoted whitespace or comma */
00212                 if ( ( isspace ( c ) || ( c == ',' ) ) && ! quote )
00213                         break;
00214 
00215                 /* Terminate if we hit a closing quote */
00216                 if ( c == quote )
00217                         break;
00218 
00219                 /* Check for value separator */
00220                 if ( value && ( ! *value ) && ( c == '=' ) ) {
00221 
00222                         /* Terminate key portion of token */
00223                         *((*line)++) = '\0';
00224 
00225                         /* Check for quote character */
00226                         c = **line;
00227                         if ( ( c == '"' ) || ( c == '\'' ) ) {
00228                                 quote = c;
00229                                 (*line)++;
00230                         }
00231 
00232                         /* Record value portion of token */
00233                         *value = *line;
00234 
00235                 } else {
00236 
00237                         /* Move to next character */
00238                         (*line)++;
00239                 }
00240         }
00241 
00242         /* Terminate token, if applicable */
00243         if ( c )
00244                 *((*line)++) = '\0';
00245 
00246         return token;
00247 }
00248 
00249 /******************************************************************************
00250  *
00251  * Transactions
00252  *
00253  ******************************************************************************
00254  */
00255 
00256 /**
00257  * Free HTTP transaction
00258  *
00259  * @v refcnt            Reference count
00260  */
00261 static void http_free ( struct refcnt *refcnt ) {
00262         struct http_transaction *http =
00263                 container_of ( refcnt, struct http_transaction, refcnt );
00264 
00265         empty_line_buffer ( &http->response.headers );
00266         empty_line_buffer ( &http->linebuf );
00267         uri_put ( http->uri );
00268         free ( http );
00269 }
00270 
00271 /**
00272  * Close HTTP transaction
00273  *
00274  * @v http              HTTP transaction
00275  * @v rc                Reason for close
00276  */
00277 static void http_close ( struct http_transaction *http, int rc ) {
00278 
00279         /* Stop process */
00280         process_del ( &http->process );
00281 
00282         /* Stop timer */
00283         stop_timer ( &http->timer );
00284 
00285         /* Close all interfaces */
00286         intfs_shutdown ( rc, &http->conn, &http->transfer, &http->content,
00287                          &http->xfer, NULL );
00288 }
00289 
00290 /**
00291  * Close HTTP transaction with error (even if none specified)
00292  *
00293  * @v http              HTTP transaction
00294  * @v rc                Reason for close
00295  */
00296 static void http_close_error ( struct http_transaction *http, int rc ) {
00297 
00298         /* Treat any close as an error */
00299         http_close ( http, ( rc ? rc : -EPIPE ) );
00300 }
00301 
00302 /**
00303  * Reopen stale HTTP connection
00304  *
00305  * @v http              HTTP transaction
00306  */
00307 static void http_reopen ( struct http_transaction *http ) {
00308         int rc;
00309 
00310         /* Close existing connection */
00311         intf_restart ( &http->conn, -ECANCELED );
00312 
00313         /* Reopen connection */
00314         if ( ( rc = http_connect ( &http->conn, http->uri ) ) != 0 ) {
00315                 DBGC ( http, "HTTP %p could not reconnect: %s\n",
00316                        http, strerror ( rc ) );
00317                 goto err_connect;
00318         }
00319 
00320         /* Reset state */
00321         http->state = &http_request;
00322 
00323         /* Reschedule transmission process */
00324         process_add ( &http->process );
00325 
00326         return;
00327 
00328  err_connect:
00329         http_close ( http, rc );
00330 }
00331 
00332 /**
00333  * Handle retry timer expiry
00334  *
00335  * @v timer             Retry timer
00336  * @v over              Failure indicator
00337  */
00338 static void http_expired ( struct retry_timer *timer, int over __unused ) {
00339         struct http_transaction *http =
00340                 container_of ( timer, struct http_transaction, timer );
00341 
00342         /* Reopen connection */
00343         http_reopen ( http );
00344 }
00345 
00346 /**
00347  * HTTP transmit process
00348  *
00349  * @v http              HTTP transaction
00350  */
00351 static void http_step ( struct http_transaction *http ) {
00352         int rc;
00353 
00354         /* Do nothing if we have nothing to transmit */
00355         if ( ! http->state->tx )
00356                 return;
00357 
00358         /* Do nothing until connection is ready */
00359         if ( ! xfer_window ( &http->conn ) )
00360                 return;
00361 
00362         /* Notify data transfer interface that window may have changed */
00363         xfer_window_changed ( &http->xfer );
00364 
00365         /* Do nothing until data transfer interface is ready */
00366         if ( ! xfer_window ( &http->xfer ) )
00367                 return;
00368 
00369         /* Transmit data */
00370         if ( ( rc = http->state->tx ( http ) ) != 0 )
00371                 goto err;
00372 
00373         return;
00374 
00375  err:
00376         http_close ( http, rc );
00377 }
00378 
00379 /**
00380  * Handle received HTTP data
00381  *
00382  * @v http              HTTP transaction
00383  * @v iobuf             I/O buffer
00384  * @v meta              Transfer metadata
00385  * @ret rc              Return status code
00386  *
00387  * This function takes ownership of the I/O buffer.
00388  */
00389 static int http_conn_deliver ( struct http_transaction *http,
00390                                struct io_buffer *iobuf,
00391                                struct xfer_metadata *meta __unused ) {
00392         int rc;
00393 
00394         /* Handle received data */
00395         profile_start ( &http_rx_profiler );
00396         while ( iobuf && iob_len ( iobuf ) ) {
00397 
00398                 /* Sanity check */
00399                 if ( ( ! http->state ) || ( ! http->state->rx ) ) {
00400                         DBGC ( http, "HTTP %p unexpected data\n", http );
00401                         rc = -EPROTO_UNSOLICITED;
00402                         goto err;
00403                 }
00404 
00405                 /* Receive (some) data */
00406                 if ( ( rc = http->state->rx ( http, &iobuf ) ) != 0 )
00407                         goto err;
00408         }
00409 
00410         /* Free I/O buffer, if applicable */
00411         free_iob ( iobuf );
00412 
00413         profile_stop ( &http_rx_profiler );
00414         return 0;
00415 
00416  err:
00417         free_iob ( iobuf );
00418         http_close ( http, rc );
00419         return rc;
00420 }
00421 
00422 /**
00423  * Handle server connection close
00424  *
00425  * @v http              HTTP transaction
00426  * @v rc                Reason for close
00427  */
00428 static void http_conn_close ( struct http_transaction *http, int rc ) {
00429 
00430         /* Sanity checks */
00431         assert ( http->state != NULL );
00432         assert ( http->state->close != NULL );
00433 
00434         /* Restart server connection interface */
00435         intf_restart ( &http->conn, rc );
00436 
00437         /* Hand off to state-specific method */
00438         http->state->close ( http, rc );
00439 }
00440 
00441 /**
00442  * Handle received content-decoded data
00443  *
00444  * @v http              HTTP transaction
00445  * @v iobuf             I/O buffer
00446  * @v meta              Data transfer metadata
00447  */
00448 static int http_content_deliver ( struct http_transaction *http,
00449                                   struct io_buffer *iobuf,
00450                                   struct xfer_metadata *meta ) {
00451         int rc;
00452 
00453         /* Ignore content if this is anything other than a successful
00454          * transfer.
00455          */
00456         if ( http->response.rc != 0 ) {
00457                 free_iob ( iobuf );
00458                 return 0;
00459         }
00460 
00461         /* Deliver to data transfer interface */
00462         profile_start ( &http_xfer_profiler );
00463         if ( ( rc = xfer_deliver ( &http->xfer, iob_disown ( iobuf ),
00464                                    meta ) ) != 0 )
00465                 return rc;
00466         profile_stop ( &http_xfer_profiler );
00467 
00468         return 0;
00469 }
00470 
00471 /**
00472  * Get underlying data transfer buffer
00473  *
00474  * @v http              HTTP transaction
00475  * @ret xferbuf         Data transfer buffer, or NULL on error
00476  */
00477 static struct xfer_buffer *
00478 http_content_buffer ( struct http_transaction *http ) {
00479 
00480         /* Deny access to the data transfer buffer if this is anything
00481          * other than a successful transfer.
00482          */
00483         if ( http->response.rc != 0 )
00484                 return NULL;
00485 
00486         /* Hand off to data transfer interface */
00487         return xfer_buffer ( &http->xfer );
00488 }
00489 
00490 /**
00491  * Read from block device (when HTTP block device support is not present)
00492  *
00493  * @v http              HTTP transaction
00494  * @v data              Data interface
00495  * @v lba               Starting logical block address
00496  * @v count             Number of logical blocks
00497  * @v buffer            Data buffer
00498  * @v len               Length of data buffer
00499  * @ret rc              Return status code
00500  */
00501 __weak int http_block_read ( struct http_transaction *http __unused,
00502                              struct interface *data __unused,
00503                              uint64_t lba __unused, unsigned int count __unused,
00504                              userptr_t buffer __unused, size_t len __unused ) {
00505 
00506         return -ENOTSUP;
00507 }
00508 
00509 /**
00510  * Read block device capacity (when HTTP block device support is not present)
00511  *
00512  * @v control           Control interface
00513  * @v data              Data interface
00514  * @ret rc              Return status code
00515  */
00516 __weak int http_block_read_capacity ( struct http_transaction *http __unused,
00517                                       struct interface *data __unused ) {
00518 
00519         return -ENOTSUP;
00520 }
00521 
00522 /** HTTP data transfer interface operations */
00523 static struct interface_operation http_xfer_operations[] = {
00524         INTF_OP ( block_read, struct http_transaction *, http_block_read ),
00525         INTF_OP ( block_read_capacity, struct http_transaction *,
00526                   http_block_read_capacity ),
00527         INTF_OP ( xfer_window_changed, struct http_transaction *, http_step ),
00528         INTF_OP ( intf_close, struct http_transaction *, http_close ),
00529 };
00530 
00531 /** HTTP data transfer interface descriptor */
00532 static struct interface_descriptor http_xfer_desc =
00533         INTF_DESC_PASSTHRU ( struct http_transaction, xfer,
00534                              http_xfer_operations, content );
00535 
00536 /** HTTP content-decoded interface operations */
00537 static struct interface_operation http_content_operations[] = {
00538         INTF_OP ( xfer_deliver, struct http_transaction *,
00539                   http_content_deliver ),
00540         INTF_OP ( xfer_buffer, struct http_transaction *, http_content_buffer ),
00541         INTF_OP ( intf_close, struct http_transaction *, http_close ),
00542 };
00543 
00544 /** HTTP content-decoded interface descriptor */
00545 static struct interface_descriptor http_content_desc =
00546         INTF_DESC_PASSTHRU ( struct http_transaction, content,
00547                              http_content_operations, xfer );
00548 
00549 /** HTTP transfer-decoded interface operations */
00550 static struct interface_operation http_transfer_operations[] = {
00551         INTF_OP ( intf_close, struct http_transaction *, http_close ),
00552 };
00553 
00554 /** HTTP transfer-decoded interface descriptor */
00555 static struct interface_descriptor http_transfer_desc =
00556         INTF_DESC_PASSTHRU ( struct http_transaction, transfer,
00557                              http_transfer_operations, conn );
00558 
00559 /** HTTP server connection interface operations */
00560 static struct interface_operation http_conn_operations[] = {
00561         INTF_OP ( xfer_deliver, struct http_transaction *, http_conn_deliver ),
00562         INTF_OP ( xfer_window_changed, struct http_transaction *, http_step ),
00563         INTF_OP ( pool_reopen, struct http_transaction *, http_reopen ),
00564         INTF_OP ( intf_close, struct http_transaction *, http_conn_close ),
00565 };
00566 
00567 /** HTTP server connection interface descriptor */
00568 static struct interface_descriptor http_conn_desc =
00569         INTF_DESC_PASSTHRU ( struct http_transaction, conn,
00570                              http_conn_operations, transfer );
00571 
00572 /** HTTP process descriptor */
00573 static struct process_descriptor http_process_desc =
00574         PROC_DESC_ONCE ( struct http_transaction, process, http_step );
00575 
00576 /**
00577  * Open HTTP transaction
00578  *
00579  * @v xfer              Data transfer interface
00580  * @v method            Request method
00581  * @v uri               Request URI
00582  * @v range             Content range (if any)
00583  * @v content           Request content (if any)
00584  * @ret rc              Return status code
00585  */
00586 int http_open ( struct interface *xfer, struct http_method *method,
00587                 struct uri *uri, struct http_request_range *range,
00588                 struct http_request_content *content ) {
00589         struct http_transaction *http;
00590         struct uri request_uri;
00591         struct uri request_host;
00592         size_t request_uri_len;
00593         size_t request_host_len;
00594         size_t content_len;
00595         char *request_uri_string;
00596         char *request_host_string;
00597         void *content_data;
00598         int rc;
00599 
00600         /* Calculate request URI length */
00601         memset ( &request_uri, 0, sizeof ( request_uri ) );
00602         request_uri.path = ( uri->path ? uri->path : "/" );
00603         request_uri.query = uri->query;
00604         request_uri_len =
00605                 ( format_uri ( &request_uri, NULL, 0 ) + 1 /* NUL */);
00606 
00607         /* Calculate host name length */
00608         memset ( &request_host, 0, sizeof ( request_host ) );
00609         request_host.host = uri->host;
00610         request_host.port = uri->port;
00611         request_host_len =
00612                 ( format_uri ( &request_host, NULL, 0 ) + 1 /* NUL */ );
00613 
00614         /* Calculate request content length */
00615         content_len = ( content ? content->len : 0 );
00616 
00617         /* Allocate and initialise structure */
00618         http = zalloc ( sizeof ( *http ) + request_uri_len + request_host_len +
00619                         content_len );
00620         if ( ! http ) {
00621                 rc = -ENOMEM;
00622                 goto err_alloc;
00623         }
00624         request_uri_string = ( ( ( void * ) http ) + sizeof ( *http ) );
00625         request_host_string = ( request_uri_string + request_uri_len );
00626         content_data = ( request_host_string + request_host_len );
00627         format_uri ( &request_uri, request_uri_string, request_uri_len );
00628         format_uri ( &request_host, request_host_string, request_host_len );
00629         ref_init ( &http->refcnt, http_free );
00630         intf_init ( &http->xfer, &http_xfer_desc, &http->refcnt );
00631         intf_init ( &http->content, &http_content_desc, &http->refcnt );
00632         intf_init ( &http->transfer, &http_transfer_desc, &http->refcnt );
00633         intf_init ( &http->conn, &http_conn_desc, &http->refcnt );
00634         intf_plug_plug ( &http->transfer, &http->content );
00635         process_init ( &http->process, &http_process_desc, &http->refcnt );
00636         timer_init ( &http->timer, http_expired, &http->refcnt );
00637         http->uri = uri_get ( uri );
00638         http->request.method = method;
00639         http->request.uri = request_uri_string;
00640         http->request.host = request_host_string;
00641         if ( range ) {
00642                 memcpy ( &http->request.range, range,
00643                          sizeof ( http->request.range ) );
00644         }
00645         if ( content ) {
00646                 http->request.content.type = content->type;
00647                 http->request.content.data = content_data;
00648                 http->request.content.len = content_len;
00649                 memcpy ( content_data, content->data, content_len );
00650         }
00651         http->state = &http_request;
00652         DBGC2 ( http, "HTTP %p %s://%s%s\n", http, http->uri->scheme,
00653                 http->request.host, http->request.uri );
00654 
00655         /* Open connection */
00656         if ( ( rc = http_connect ( &http->conn, uri ) ) != 0 ) {
00657                 DBGC ( http, "HTTP %p could not connect: %s\n",
00658                        http, strerror ( rc ) );
00659                 goto err_connect;
00660         }
00661 
00662         /* Attach to parent interface, mortalise self, and return */
00663         intf_plug_plug ( &http->xfer, xfer );
00664         ref_put ( &http->refcnt );
00665         return 0;
00666 
00667  err_connect:
00668         http_close ( http, rc );
00669         ref_put ( &http->refcnt );
00670  err_alloc:
00671         return rc;
00672 }
00673 
00674 /**
00675  * Redirect HTTP transaction
00676  *
00677  * @v http              HTTP transaction
00678  * @v location          New location
00679  * @ret rc              Return status code
00680  */
00681 static int http_redirect ( struct http_transaction *http,
00682                            const char *location ) {
00683         struct uri *location_uri;
00684         struct uri *resolved_uri;
00685         int rc;
00686 
00687         DBGC2 ( http, "HTTP %p redirecting to \"%s\"\n", http, location );
00688 
00689         /* Parse location URI */
00690         location_uri = parse_uri ( location );
00691         if ( ! location_uri ) {
00692                 rc = -ENOMEM;
00693                 goto err_parse_uri;
00694         }
00695 
00696         /* Resolve as relative to original URI */
00697         resolved_uri = resolve_uri ( http->uri, location_uri );
00698         if ( ! resolved_uri ) {
00699                 rc = -ENOMEM;
00700                 goto err_resolve_uri;
00701         }
00702 
00703         /* Redirect to new URI */
00704         if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI,
00705                                     resolved_uri ) ) != 0 ) {
00706                 DBGC ( http, "HTTP %p could not redirect: %s\n",
00707                        http, strerror ( rc ) );
00708                 goto err_redirect;
00709         }
00710 
00711  err_redirect:
00712         uri_put ( resolved_uri );
00713  err_resolve_uri:
00714         uri_put ( location_uri );
00715  err_parse_uri:
00716         return rc;
00717 }
00718 
00719 /**
00720  * Handle successful transfer completion
00721  *
00722  * @v http              HTTP transaction
00723  * @ret rc              Return status code
00724  */
00725 static int http_transfer_complete ( struct http_transaction *http ) {
00726         struct http_authentication *auth;
00727         const char *location;
00728         int rc;
00729 
00730         /* Keep connection alive if applicable */
00731         if ( http->response.flags & HTTP_RESPONSE_KEEPALIVE )
00732                 pool_recycle ( &http->conn );
00733 
00734         /* Restart server connection interface */
00735         intf_restart ( &http->conn, 0 );
00736 
00737         /* No more data is expected */
00738         http->state = NULL;
00739 
00740         /* If transaction is successful, then close the
00741          * transfer-decoded interface.  The content encoding may
00742          * choose whether or not to immediately terminate the
00743          * transaction.
00744          */
00745         if ( http->response.rc == 0 ) {
00746                 intf_shutdown ( &http->transfer, 0 );
00747                 return 0;
00748         }
00749 
00750         /* Perform redirection, if applicable */
00751         if ( ( location = http->response.location ) ) {
00752                 if ( ( rc = http_redirect ( http, location ) ) != 0 )
00753                         return rc;
00754                 http_close ( http, 0 );
00755                 return 0;
00756         }
00757 
00758         /* Fail unless a retry is permitted */
00759         if ( ! ( http->response.flags & HTTP_RESPONSE_RETRY ) )
00760                 return http->response.rc;
00761 
00762         /* Perform authentication, if applicable */
00763         if ( ( auth = http->response.auth.auth ) ) {
00764                 http->request.auth.auth = auth;
00765                 DBGC2 ( http, "HTTP %p performing %s authentication\n",
00766                         http, auth->name );
00767                 if ( ( rc = auth->authenticate ( http ) ) != 0 ) {
00768                         DBGC ( http, "HTTP %p could not authenticate: %s\n",
00769                                http, strerror ( rc ) );
00770                         return rc;
00771                 }
00772         }
00773 
00774         /* Restart content decoding interfaces */
00775         intfs_restart ( http->response.rc, &http->content, &http->transfer,
00776                         NULL );
00777         intf_plug_plug ( &http->transfer, &http->content );
00778         http->len = 0;
00779         assert ( http->remaining == 0 );
00780 
00781         /* Retry immediately if applicable.  We cannot rely on an
00782          * immediate timer expiry, since certain Microsoft-designed
00783          * HTTP extensions such as NTLM break the fundamentally
00784          * stateless nature of HTTP and rely on the same connection
00785          * being reused for authentication.  See RFC7230 section 2.3
00786          * for further details.
00787          */
00788         if ( ! http->response.retry_after ) {
00789                 http_reopen ( http );
00790                 return 0;
00791         }
00792 
00793         /* Start timer to initiate retry */
00794         DBGC2 ( http, "HTTP %p retrying after %d seconds\n",
00795                 http, http->response.retry_after );
00796         start_timer_fixed ( &http->timer,
00797                             ( http->response.retry_after * TICKS_PER_SEC ) );
00798         return 0;
00799 }
00800 
00801 /******************************************************************************
00802  *
00803  * Requests
00804  *
00805  ******************************************************************************
00806  */
00807 
00808 /**
00809  * Construct HTTP request headers
00810  *
00811  * @v http              HTTP transaction
00812  * @v buf               Buffer
00813  * @v len               Length of buffer
00814  * @ret len             Length, or negative error
00815  */
00816 static int http_format_headers ( struct http_transaction *http, char *buf,
00817                                  size_t len ) {
00818         struct http_request_header *header;
00819         size_t used;
00820         size_t remaining;
00821         char *line;
00822         int value_len;
00823         int rc;
00824 
00825         /* Construct request line */
00826         used = ssnprintf ( buf, len, "%s %s HTTP/1.1",
00827                            http->request.method->name, http->request.uri );
00828         if ( used < len )
00829                 DBGC2 ( http, "HTTP %p TX %s\n", http, buf );
00830         used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" );
00831 
00832         /* Construct all headers */
00833         for_each_table_entry ( header, HTTP_REQUEST_HEADERS ) {
00834 
00835                 /* Determine header value length */
00836                 value_len = header->format ( http, NULL, 0 );
00837                 if ( value_len < 0 ) {
00838                         rc = value_len;
00839                         return rc;
00840                 }
00841 
00842                 /* Skip zero-length headers */
00843                 if ( ! value_len )
00844                         continue;
00845 
00846                 /* Construct header */
00847                 line = ( buf + used );
00848                 used += ssnprintf ( ( buf + used ), ( len - used ), "%s: ",
00849                                     header->name );
00850                 remaining = ( ( used < len ) ? ( len - used ) : 0 );
00851                 used += header->format ( http, ( buf + used ), remaining );
00852                 if ( used < len )
00853                         DBGC2 ( http, "HTTP %p TX %s\n", http, line );
00854                 used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" );
00855         }
00856 
00857         /* Construct terminating newline */
00858         used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" );
00859 
00860         return used;
00861 }
00862 
00863 /**
00864  * Construct HTTP "Host" header
00865  *
00866  * @v http              HTTP transaction
00867  * @v buf               Buffer
00868  * @v len               Length of buffer
00869  * @ret len             Length of header value, or negative error
00870  */
00871 static int http_format_host ( struct http_transaction *http, char *buf,
00872                               size_t len ) {
00873 
00874         /* Construct host URI */
00875         return snprintf ( buf, len, "%s", http->request.host );
00876 }
00877 
00878 /** HTTP "Host" header "*/
00879 struct http_request_header http_request_host __http_request_header = {
00880         .name = "Host",
00881         .format = http_format_host,
00882 };
00883 
00884 /**
00885  * Construct HTTP "User-Agent" header
00886  *
00887  * @v http              HTTP transaction
00888  * @v buf               Buffer
00889  * @v len               Length of buffer
00890  * @ret len             Length of header value, or negative error
00891  */
00892 static int http_format_user_agent ( struct http_transaction *http __unused,
00893                                     char *buf, size_t len ) {
00894 
00895         /* Construct user agent */
00896         return snprintf ( buf, len, "iPXE/%s", product_version );
00897 }
00898 
00899 /** HTTP "User-Agent" header */
00900 struct http_request_header http_request_user_agent __http_request_header = {
00901         .name = "User-Agent",
00902         .format = http_format_user_agent,
00903 };
00904 
00905 /**
00906  * Construct HTTP "Connection" header
00907  *
00908  * @v http              HTTP transaction
00909  * @v buf               Buffer
00910  * @v len               Length of buffer
00911  * @ret len             Length of header value, or negative error
00912  */
00913 static int http_format_connection ( struct http_transaction *http __unused,
00914                                     char *buf, size_t len ) {
00915 
00916         /* Always request keep-alive */
00917         return snprintf ( buf, len, "keep-alive" );
00918 }
00919 
00920 /** HTTP "Connection" header */
00921 struct http_request_header http_request_connection __http_request_header = {
00922         .name = "Connection",
00923         .format = http_format_connection,
00924 };
00925 
00926 /**
00927  * Construct HTTP "Range" header
00928  *
00929  * @v http              HTTP transaction
00930  * @v buf               Buffer
00931  * @v len               Length of buffer
00932  * @ret len             Length of header value, or negative error
00933  */
00934 static int http_format_range ( struct http_transaction *http,
00935                                char *buf, size_t len ) {
00936 
00937         /* Construct range, if applicable */
00938         if ( http->request.range.len ) {
00939                 return snprintf ( buf, len, "bytes=%zd-%zd",
00940                                   http->request.range.start,
00941                                   ( http->request.range.start +
00942                                     http->request.range.len - 1 ) );
00943         } else {
00944                 return 0;
00945         }
00946 }
00947 
00948 /** HTTP "Range" header */
00949 struct http_request_header http_request_range __http_request_header = {
00950         .name = "Range",
00951         .format = http_format_range,
00952 };
00953 
00954 /**
00955  * Construct HTTP "Content-Type" header
00956  *
00957  * @v http              HTTP transaction
00958  * @v buf               Buffer
00959  * @v len               Length of buffer
00960  * @ret len             Length of header value, or negative error
00961  */
00962 static int http_format_content_type ( struct http_transaction *http,
00963                                       char *buf, size_t len ) {
00964 
00965         /* Construct content type, if applicable */
00966         if ( http->request.content.type ) {
00967                 return snprintf ( buf, len, "%s", http->request.content.type );
00968         } else {
00969                 return 0;
00970         }
00971 }
00972 
00973 /** HTTP "Content-Type" header */
00974 struct http_request_header http_request_content_type __http_request_header = {
00975         .name = "Content-Type",
00976         .format = http_format_content_type,
00977 };
00978 
00979 /**
00980  * Construct HTTP "Content-Length" header
00981  *
00982  * @v http              HTTP transaction
00983  * @v buf               Buffer
00984  * @v len               Length of buffer
00985  * @ret len             Length of header value, or negative error
00986  */
00987 static int http_format_content_length ( struct http_transaction *http,
00988                                         char *buf, size_t len ) {
00989 
00990         /* Construct content length, if applicable */
00991         if ( http->request.content.len ) {
00992                 return snprintf ( buf, len, "%zd", http->request.content.len );
00993         } else {
00994                 return 0;
00995         }
00996 }
00997 
00998 /** HTTP "Content-Length" header */
00999 struct http_request_header http_request_content_length __http_request_header = {
01000         .name = "Content-Length",
01001         .format = http_format_content_length,
01002 };
01003 
01004 /**
01005  * Construct HTTP "Accept-Encoding" header
01006  *
01007  * @v http              HTTP transaction
01008  * @v buf               Buffer
01009  * @v len               Length of buffer
01010  * @ret len             Length of header value, or negative error
01011  */
01012 static int http_format_accept_encoding ( struct http_transaction *http,
01013                                          char *buf, size_t len ) {
01014         struct http_content_encoding *encoding;
01015         const char *sep = "";
01016         size_t used = 0;
01017 
01018         /* Construct list of content encodings */
01019         for_each_table_entry ( encoding, HTTP_CONTENT_ENCODINGS ) {
01020                 if ( encoding->supported && ( ! encoding->supported ( http ) ) )
01021                         continue;
01022                 used += ssnprintf ( ( buf + used ), ( len - used ),
01023                                     "%s%s", sep, encoding->name );
01024                 sep = ", ";
01025         }
01026 
01027         return used;
01028 }
01029 
01030 /** HTTP "Accept-Encoding" header */
01031 struct http_request_header http_request_accept_encoding __http_request_header ={
01032         .name = "Accept-Encoding",
01033         .format = http_format_accept_encoding,
01034 };
01035 
01036 /**
01037  * Transmit request
01038  *
01039  * @v http              HTTP transaction
01040  * @ret rc              Return status code
01041  */
01042 static int http_tx_request ( struct http_transaction *http ) {
01043         struct io_buffer *iobuf;
01044         int len;
01045         int check_len;
01046         int rc;
01047 
01048         /* Calculate request length */
01049         len = http_format_headers ( http, NULL, 0 );
01050         if ( len < 0 ) {
01051                 rc = len;
01052                 DBGC ( http, "HTTP %p could not construct request: %s\n",
01053                        http, strerror ( rc ) );
01054                 goto err_len;
01055         }
01056 
01057         /* Allocate I/O buffer */
01058         iobuf = alloc_iob ( len + 1 /* NUL */ + http->request.content.len );
01059         if ( ! iobuf ) {
01060                 rc = -ENOMEM;
01061                 goto err_alloc;
01062         }
01063 
01064         /* Construct request */
01065         check_len = http_format_headers ( http, iob_put ( iobuf, len ),
01066                                           ( len + 1 /* NUL */ ) );
01067         assert ( check_len == len );
01068         memcpy ( iob_put ( iobuf, http->request.content.len ),
01069                  http->request.content.data, http->request.content.len );
01070 
01071         /* Deliver request */
01072         if ( ( rc = xfer_deliver_iob ( &http->conn,
01073                                        iob_disown ( iobuf ) ) ) != 0 ) {
01074                 DBGC ( http, "HTTP %p could not deliver request: %s\n",
01075                        http, strerror ( rc ) );
01076                 goto err_deliver;
01077         }
01078 
01079         /* Clear any previous response */
01080         empty_line_buffer ( &http->response.headers );
01081         memset ( &http->response, 0, sizeof ( http->response ) );
01082 
01083         /* Move to response headers state */
01084         http->state = &http_headers;
01085 
01086         return 0;
01087 
01088  err_deliver:
01089         free_iob ( iobuf );
01090  err_alloc:
01091  err_len:
01092         return rc;
01093 }
01094 
01095 /** HTTP request state */
01096 static struct http_state http_request = {
01097         .tx = http_tx_request,
01098         .close = http_close_error,
01099 };
01100 
01101 /******************************************************************************
01102  *
01103  * Response headers
01104  *
01105  ******************************************************************************
01106  */
01107 
01108 /**
01109  * Parse HTTP status line
01110  *
01111  * @v http              HTTP transaction
01112  * @v line              Status line
01113  * @ret rc              Return status code
01114  */
01115 static int http_parse_status ( struct http_transaction *http, char *line ) {
01116         char *endp;
01117         char *version;
01118         char *vernum;
01119         char *status;
01120         int response_rc;
01121 
01122         DBGC2 ( http, "HTTP %p RX %s\n", http, line );
01123 
01124         /* Parse HTTP version */
01125         version = http_token ( &line, NULL );
01126         if ( ( ! version ) || ( strncmp ( version, "HTTP/", 5 ) != 0 ) ) {
01127                 DBGC ( http, "HTTP %p malformed version \"%s\"\n", http, line );
01128                 return -EINVAL_STATUS;
01129         }
01130 
01131         /* Keepalive is enabled by default for anything newer than HTTP/1.0 */
01132         vernum = ( version + 5 /* "HTTP/" (presence already checked) */ );
01133         if ( vernum[0] == '0' ) {
01134                 /* HTTP/0.x : keepalive not enabled by default */
01135         } else if ( strncmp ( vernum, "1.0", 3 ) == 0 ) {
01136                 /* HTTP/1.0 : keepalive not enabled by default */
01137         } else {
01138                 /* HTTP/1.1 or newer: keepalive enabled by default */
01139                 http->response.flags |= HTTP_RESPONSE_KEEPALIVE;
01140         }
01141 
01142         /* Parse status code */
01143         status = line;
01144         http->response.status = strtoul ( status, &endp, 10 );
01145         if ( *endp != ' ' ) {
01146                 DBGC ( http, "HTTP %p malformed status code \"%s\"\n",
01147                        http, status );
01148                 return -EINVAL_STATUS;
01149         }
01150 
01151         /* Convert HTTP status code to iPXE return status code */
01152         if ( status[0] == '2' ) {
01153                 /* 2xx Success */
01154                 response_rc = 0;
01155         } else if ( status[0] == '3' ) {
01156                 /* 3xx Redirection */
01157                 response_rc = -EXDEV;
01158         } else if ( http->response.status == 401 ) {
01159                 /* 401 Unauthorized */
01160                 response_rc = -EACCES_401;
01161         } else if ( http->response.status == 403 ) {
01162                 /* 403 Forbidden */
01163                 response_rc = -EPERM_403;
01164         } else if ( http->response.status == 404 ) {
01165                 /* 404 Not Found */
01166                 response_rc = -ENOENT_404;
01167         } else if ( status[0] == '4' ) {
01168                 /* 4xx Client Error (not already specified) */
01169                 response_rc = -EIO_4XX;
01170         } else if ( status[0] == '5' ) {
01171                 /* 5xx Server Error */
01172                 response_rc = -EIO_5XX;
01173         } else {
01174                 /* Unrecognised */
01175                 response_rc = -EIO_OTHER;
01176         }
01177         http->response.rc = response_rc;
01178         if ( response_rc )
01179                 DBGC ( http, "HTTP %p status %s\n", http, status );
01180 
01181         return 0;
01182 }
01183 
01184 /**
01185  * Parse HTTP header
01186  *
01187  * @v http              HTTP transaction
01188  * @v line              Header line
01189  * @ret rc              Return status code
01190  */
01191 static int http_parse_header ( struct http_transaction *http, char *line ) {
01192         struct http_response_header *header;
01193         char *name = line;
01194         char *sep;
01195 
01196         DBGC2 ( http, "HTTP %p RX %s\n", http, line );
01197 
01198         /* Extract header name */
01199         sep = strchr ( line, ':' );
01200         if ( ! sep ) {
01201                 DBGC ( http, "HTTP %p malformed header \"%s\"\n", http, line );
01202                 return -EINVAL_HEADER;
01203         }
01204         *sep = '\0';
01205 
01206         /* Extract remainder of line */
01207         line = ( sep + 1 );
01208         while ( isspace ( *line ) )
01209                 line++;
01210 
01211         /* Process header, if recognised */
01212         for_each_table_entry ( header, HTTP_RESPONSE_HEADERS ) {
01213                 if ( strcasecmp ( name, header->name ) == 0 )
01214                         return header->parse ( http, line );
01215         }
01216 
01217         /* Unrecognised headers should be ignored */
01218         return 0;
01219 }
01220 
01221 /**
01222  * Parse HTTP response headers
01223  *
01224  * @v http              HTTP transaction
01225  * @ret rc              Return status code
01226  */
01227 static int http_parse_headers ( struct http_transaction *http ) {
01228         char *line;
01229         char *next;
01230         int rc;
01231 
01232         /* Get status line */
01233         line = http->response.headers.data;
01234         assert ( line != NULL );
01235         next = ( line + strlen ( line ) + 1 /* NUL */ );
01236 
01237         /* Parse status line */
01238         if ( ( rc = http_parse_status ( http, line ) ) != 0 )
01239                 return rc;
01240 
01241         /* Process header lines */
01242         while ( 1 ) {
01243 
01244                 /* Move to next line */
01245                 line = next;
01246                 next = ( line + strlen ( line ) + 1 /* NUL */ );
01247 
01248                 /* Stop on terminating blank line */
01249                 if ( ! line[0] )
01250                         return 0;
01251 
01252                 /* Process header line */
01253                 if ( ( rc = http_parse_header ( http, line ) ) != 0 )
01254                         return rc;
01255         }
01256 }
01257 
01258 /**
01259  * Parse HTTP "Location" header
01260  *
01261  * @v http              HTTP transaction
01262  * @v line              Remaining header line
01263  * @ret rc              Return status code
01264  */
01265 static int http_parse_location ( struct http_transaction *http, char *line ) {
01266 
01267         /* Store location */
01268         http->response.location = line;
01269         return 0;
01270 }
01271 
01272 /** HTTP "Location" header */
01273 struct http_response_header http_response_location __http_response_header = {
01274         .name = "Location",
01275         .parse = http_parse_location,
01276 };
01277 
01278 /**
01279  * Parse HTTP "Transfer-Encoding" header
01280  *
01281  * @v http              HTTP transaction
01282  * @v line              Remaining header line
01283  * @ret rc              Return status code
01284  */
01285 static int http_parse_transfer_encoding ( struct http_transaction *http,
01286                                           char *line ) {
01287         struct http_transfer_encoding *encoding;
01288 
01289         /* Check for known transfer encodings */
01290         for_each_table_entry ( encoding, HTTP_TRANSFER_ENCODINGS ) {
01291                 if ( strcasecmp ( line, encoding->name ) == 0 ) {
01292                         http->response.transfer.encoding = encoding;
01293                         return 0;
01294                 }
01295         }
01296 
01297         DBGC ( http, "HTTP %p unrecognised Transfer-Encoding \"%s\"\n",
01298                http, line );
01299         return -ENOTSUP_TRANSFER;
01300 }
01301 
01302 /** HTTP "Transfer-Encoding" header */
01303 struct http_response_header
01304 http_response_transfer_encoding __http_response_header = {
01305         .name = "Transfer-Encoding",
01306         .parse = http_parse_transfer_encoding,
01307 };
01308 
01309 /**
01310  * Parse HTTP "Connection" header
01311  *
01312  * @v http              HTTP transaction
01313  * @v line              Remaining header line
01314  * @ret rc              Return status code
01315  */
01316 static int http_parse_connection ( struct http_transaction *http, char *line ) {
01317         char *token;
01318 
01319         /* Check for known connection intentions */
01320         while ( ( token = http_token ( &line, NULL ) ) ) {
01321                 if ( strcasecmp ( token, "keep-alive" ) == 0 )
01322                         http->response.flags |= HTTP_RESPONSE_KEEPALIVE;
01323                 if ( strcasecmp ( token, "close" ) == 0 )
01324                         http->response.flags &= ~HTTP_RESPONSE_KEEPALIVE;
01325         }
01326 
01327         return 0;
01328 }
01329 
01330 /** HTTP "Connection" header */
01331 struct http_response_header http_response_connection __http_response_header = {
01332         .name = "Connection",
01333         .parse = http_parse_connection,
01334 };
01335 
01336 /**
01337  * Parse HTTP "Content-Length" header
01338  *
01339  * @v http              HTTP transaction
01340  * @v line              Remaining header line
01341  * @ret rc              Return status code
01342  */
01343 static int http_parse_content_length ( struct http_transaction *http,
01344                                        char *line ) {
01345         char *endp;
01346 
01347         /* Parse length */
01348         http->response.content.len = strtoul ( line, &endp, 10 );
01349         if ( *endp != '\0' ) {
01350                 DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n",
01351                        http, line );
01352                 return -EINVAL_CONTENT_LENGTH;
01353         }
01354 
01355         /* Record that we have a content length (since it may be zero) */
01356         http->response.flags |= HTTP_RESPONSE_CONTENT_LEN;
01357 
01358         return 0;
01359 }
01360 
01361 /** HTTP "Content-Length" header */
01362 struct http_response_header
01363 http_response_content_length __http_response_header = {
01364         .name = "Content-Length",
01365         .parse = http_parse_content_length,
01366 };
01367 
01368 /**
01369  * Parse HTTP "Content-Encoding" header
01370  *
01371  * @v http              HTTP transaction
01372  * @v line              Remaining header line
01373  * @ret rc              Return status code
01374  */
01375 static int http_parse_content_encoding ( struct http_transaction *http,
01376                                          char *line ) {
01377         struct http_content_encoding *encoding;
01378 
01379         /* Check for known content encodings */
01380         for_each_table_entry ( encoding, HTTP_CONTENT_ENCODINGS ) {
01381                 if ( encoding->supported && ( ! encoding->supported ( http ) ) )
01382                         continue;
01383                 if ( strcasecmp ( line, encoding->name ) == 0 ) {
01384                         http->response.content.encoding = encoding;
01385                         return 0;
01386                 }
01387         }
01388 
01389         /* Some servers (e.g. Apache) have a habit of specifying
01390          * unwarranted content encodings.  For example, if Apache
01391          * detects (via /etc/httpd/conf/magic) that a file's contents
01392          * are gzip-compressed, it will set "Content-Encoding: x-gzip"
01393          * regardless of the client's Accept-Encoding header.  The
01394          * only viable way to handle such servers is to treat unknown
01395          * content encodings as equivalent to "identity".
01396          */
01397         DBGC ( http, "HTTP %p unrecognised Content-Encoding \"%s\"\n",
01398                http, line );
01399         return 0;
01400 }
01401 
01402 /** HTTP "Content-Encoding" header */
01403 struct http_response_header
01404 http_response_content_encoding __http_response_header = {
01405         .name = "Content-Encoding",
01406         .parse = http_parse_content_encoding,
01407 };
01408 
01409 /**
01410  * Parse HTTP "Retry-After" header
01411  *
01412  * @v http              HTTP transaction
01413  * @v line              Remaining header line
01414  * @ret rc              Return status code
01415  */
01416 static int http_parse_retry_after ( struct http_transaction *http,
01417                                     char *line ) {
01418         char *endp;
01419 
01420         /* Try to parse value as a simple number of seconds */
01421         http->response.retry_after = strtoul ( line, &endp, 10 );
01422         if ( *endp != '\0' ) {
01423                 /* For any value which is not a simple number of
01424                  * seconds (e.g. a full HTTP date), just retry after a
01425                  * fixed delay, since we don't have code able to parse
01426                  * full HTTP dates.
01427                  */
01428                 http->response.retry_after = HTTP_RETRY_SECONDS;
01429                 DBGC ( http, "HTTP %p cannot understand Retry-After \"%s\"; "
01430                        "using %d seconds\n", http, line, HTTP_RETRY_SECONDS );
01431         }
01432 
01433         /* Allow HTTP request to be retried after specified delay */
01434         http->response.flags |= HTTP_RESPONSE_RETRY;
01435 
01436         return 0;
01437 }
01438 
01439 /** HTTP "Retry-After" header */
01440 struct http_response_header http_response_retry_after __http_response_header = {
01441         .name = "Retry-After",
01442         .parse = http_parse_retry_after,
01443 };
01444 
01445 /**
01446  * Handle received HTTP headers
01447  *
01448  * @v http              HTTP transaction
01449  * @v iobuf             I/O buffer (may be claimed)
01450  * @ret rc              Return status code
01451  */
01452 static int http_rx_headers ( struct http_transaction *http,
01453                              struct io_buffer **iobuf ) {
01454         struct http_transfer_encoding *transfer;
01455         struct http_content_encoding *content;
01456         char *line;
01457         int rc;
01458 
01459         /* Buffer header line */
01460         if ( ( rc = http_rx_linebuf ( http, *iobuf,
01461                                       &http->response.headers ) ) != 0 )
01462                 return rc;
01463 
01464         /* Wait until we see the empty line marking end of headers */
01465         line = buffered_line ( &http->response.headers );
01466         if ( ( line == NULL ) || ( line[0] != '\0' ) )
01467                 return 0;
01468 
01469         /* Process headers */
01470         if ( ( rc = http_parse_headers ( http ) ) != 0 )
01471                 return rc;
01472 
01473         /* Initialise content encoding, if applicable */
01474         if ( ( content = http->response.content.encoding ) &&
01475              ( ( rc = content->init ( http ) ) != 0 ) ) {
01476                 DBGC ( http, "HTTP %p could not initialise %s content "
01477                        "encoding: %s\n", http, content->name, strerror ( rc ) );
01478                 return rc;
01479         }
01480 
01481         /* Presize receive buffer, if we have a content length */
01482         if ( http->response.content.len ) {
01483                 xfer_seek ( &http->transfer, http->response.content.len );
01484                 xfer_seek ( &http->transfer, 0 );
01485         }
01486 
01487         /* Complete transfer if this is a HEAD request */
01488         if ( http->request.method == &http_head ) {
01489                 if ( ( rc = http_transfer_complete ( http ) ) != 0 )
01490                         return rc;
01491                 return 0;
01492         }
01493 
01494         /* Default to identity transfer encoding, if none specified */
01495         if ( ! http->response.transfer.encoding )
01496                 http->response.transfer.encoding = &http_transfer_identity;
01497 
01498         /* Move to transfer encoding-specific data state */
01499         transfer = http->response.transfer.encoding;
01500         http->state = &transfer->state;
01501 
01502         /* Initialise transfer encoding */
01503         if ( ( rc = transfer->init ( http ) ) != 0 ) {
01504                 DBGC ( http, "HTTP %p could not initialise %s transfer "
01505                        "encoding: %s\n", http, transfer->name, strerror ( rc ));
01506                 return rc;
01507         }
01508 
01509         return 0;
01510 }
01511 
01512 /** HTTP response headers state */
01513 static struct http_state http_headers = {
01514         .rx = http_rx_headers,
01515         .close = http_close_error,
01516 };
01517 
01518 /******************************************************************************
01519  *
01520  * Identity transfer encoding
01521  *
01522  ******************************************************************************
01523  */
01524 
01525 /**
01526  * Initialise transfer encoding
01527  *
01528  * @v http              HTTP transaction
01529  * @ret rc              Return status code
01530  */
01531 static int http_init_transfer_identity ( struct http_transaction *http ) {
01532         int rc;
01533 
01534         /* Complete transfer immediately if we have a zero content length */
01535         if ( ( http->response.flags & HTTP_RESPONSE_CONTENT_LEN ) &&
01536              ( http->response.content.len == 0 ) &&
01537              ( ( rc = http_transfer_complete ( http ) ) != 0 ) )
01538                 return rc;
01539 
01540         return 0;
01541 }
01542 
01543 /**
01544  * Handle received data
01545  *
01546  * @v http              HTTP transaction
01547  * @v iobuf             I/O buffer (may be claimed)
01548  * @ret rc              Return status code
01549  */
01550 static int http_rx_transfer_identity ( struct http_transaction *http,
01551                                        struct io_buffer **iobuf ) {
01552         size_t len = iob_len ( *iobuf );
01553         int rc;
01554 
01555         /* Update lengths */
01556         http->len += len;
01557 
01558         /* Fail if this transfer would overrun the expected content
01559          * length (if any).
01560          */
01561         if ( ( http->response.flags & HTTP_RESPONSE_CONTENT_LEN ) &&
01562              ( http->len > http->response.content.len ) ) {
01563                 DBGC ( http, "HTTP %p content length overrun\n", http );
01564                 return -EIO_CONTENT_LENGTH;
01565         }
01566 
01567         /* Hand off to content encoding */
01568         if ( ( rc = xfer_deliver_iob ( &http->transfer,
01569                                        iob_disown ( *iobuf ) ) ) != 0 )
01570                 return rc;
01571 
01572         /* Complete transfer if we have received the expected content
01573          * length (if any).
01574          */
01575         if ( ( http->response.flags & HTTP_RESPONSE_CONTENT_LEN ) &&
01576              ( http->len == http->response.content.len ) &&
01577              ( ( rc = http_transfer_complete ( http ) ) != 0 ) )
01578                 return rc;
01579 
01580         return 0;
01581 }
01582 
01583 /**
01584  * Handle server connection close
01585  *
01586  * @v http              HTTP transaction
01587  * @v rc                Reason for close
01588  */
01589 static void http_close_transfer_identity ( struct http_transaction *http,
01590                                            int rc ) {
01591 
01592         /* Fail if any error occurred */
01593         if ( rc != 0 )
01594                 goto err;
01595 
01596         /* Fail if we have a content length (since we would have
01597          * already closed the connection if we had received the
01598          * correct content length).
01599          */
01600         if ( http->response.flags & HTTP_RESPONSE_CONTENT_LEN ) {
01601                 DBGC ( http, "HTTP %p content length underrun\n", http );
01602                 rc = EIO_CONTENT_LENGTH;
01603                 goto err;
01604         }
01605 
01606         /* Indicate that transfer is complete */
01607         if ( ( rc = http_transfer_complete ( http ) ) != 0 )
01608                 goto err;
01609 
01610         return;
01611 
01612  err:
01613         http_close ( http, rc );
01614 }
01615 
01616 /** Identity transfer encoding */
01617 static struct http_transfer_encoding http_transfer_identity = {
01618         .name = "identity",
01619         .init = http_init_transfer_identity,
01620         .state = {
01621                 .rx = http_rx_transfer_identity,
01622                 .close = http_close_transfer_identity,
01623         },
01624 };
01625 
01626 /******************************************************************************
01627  *
01628  * Chunked transfer encoding
01629  *
01630  ******************************************************************************
01631  */
01632 
01633 /**
01634  * Initialise transfer encoding
01635  *
01636  * @v http              HTTP transaction
01637  * @ret rc              Return status code
01638  */
01639 static int http_init_transfer_chunked ( struct http_transaction *http ) {
01640 
01641         /* Sanity checks */
01642         assert ( http->remaining == 0 );
01643         assert ( http->linebuf.len == 0 );
01644 
01645         return 0;
01646 }
01647 
01648 /**
01649  * Handle received chunk length
01650  *
01651  * @v http              HTTP transaction
01652  * @v iobuf             I/O buffer (may be claimed)
01653  * @ret rc              Return status code
01654  */
01655 static int http_rx_chunk_len ( struct http_transaction *http,
01656                                struct io_buffer **iobuf ) {
01657         char *line;
01658         char *endp;
01659         size_t len;
01660         int rc;
01661 
01662         /* Receive into temporary line buffer */
01663         if ( ( rc = http_rx_linebuf ( http, *iobuf, &http->linebuf ) ) != 0 )
01664                 return rc;
01665 
01666         /* Wait until we receive a non-empty line */
01667         line = buffered_line ( &http->linebuf );
01668         if ( ( line == NULL ) || ( line[0] == '\0' ) )
01669                 return 0;
01670 
01671         /* Parse chunk length */
01672         http->remaining = strtoul ( line, &endp, 16 );
01673         if ( *endp != '\0' ) {
01674                 DBGC ( http, "HTTP %p invalid chunk length \"%s\"\n",
01675                        http, line );
01676                 return -EINVAL_CHUNK_LENGTH;
01677         }
01678 
01679         /* Empty line buffer */
01680         empty_line_buffer ( &http->linebuf );
01681 
01682         /* Update expected length */
01683         len = ( http->len + http->remaining );
01684         xfer_seek ( &http->transfer, len );
01685         xfer_seek ( &http->transfer, http->len );
01686 
01687         /* If chunk length is zero, then move to response trailers state */
01688         if ( ! http->remaining )
01689                 http->state = &http_trailers;
01690 
01691         return 0;
01692 }
01693 
01694 /**
01695  * Handle received chunk data
01696  *
01697  * @v http              HTTP transaction
01698  * @v iobuf             I/O buffer (may be claimed)
01699  * @ret rc              Return status code
01700  */
01701 static int http_rx_chunk_data ( struct http_transaction *http,
01702                                 struct io_buffer **iobuf ) {
01703         struct io_buffer *payload;
01704         uint8_t *crlf;
01705         size_t len;
01706         int rc;
01707 
01708         /* In the common case of a final chunk in a packet which also
01709          * includes the terminating CRLF, strip the terminating CRLF
01710          * (which we would ignore anyway) and hence avoid
01711          * unnecessarily copying the data.
01712          */
01713         if ( iob_len ( *iobuf ) == ( http->remaining + 2 /* CRLF */ ) ) {
01714                 crlf = ( (*iobuf)->data + http->remaining );
01715                 if ( ( crlf[0] == '\r' ) && ( crlf[1] == '\n' ) )
01716                         iob_unput ( (*iobuf), 2 /* CRLF */ );
01717         }
01718         len = iob_len ( *iobuf );
01719 
01720         /* Use whole/partial buffer as applicable */
01721         if ( len <= http->remaining ) {
01722 
01723                 /* Whole buffer is to be consumed: decrease remaining
01724                  * length and use original I/O buffer as payload.
01725                  */
01726                 payload = iob_disown ( *iobuf );
01727                 http->len += len;
01728                 http->remaining -= len;
01729 
01730         } else {
01731 
01732                 /* Partial buffer is to be consumed: copy data to a
01733                  * temporary I/O buffer.
01734                  */
01735                 payload = alloc_iob ( http->remaining );
01736                 if ( ! payload ) {
01737                         rc = -ENOMEM;
01738                         goto err;
01739                 }
01740                 memcpy ( iob_put ( payload, http->remaining ), (*iobuf)->data,
01741                          http->remaining );
01742                 iob_pull ( *iobuf, http->remaining );
01743                 http->len += http->remaining;
01744                 http->remaining = 0;
01745         }
01746 
01747         /* Hand off to content encoding */
01748         if ( ( rc = xfer_deliver_iob ( &http->transfer,
01749                                        iob_disown ( payload ) ) ) != 0 )
01750                 goto err;
01751 
01752         return 0;
01753 
01754  err:
01755         assert ( payload == NULL );
01756         return rc;
01757 }
01758 
01759 /**
01760  * Handle received chunked data
01761  *
01762  * @v http              HTTP transaction
01763  * @v iobuf             I/O buffer (may be claimed)
01764  * @ret rc              Return status code
01765  */
01766 static int http_rx_transfer_chunked ( struct http_transaction *http,
01767                                       struct io_buffer **iobuf ) {
01768 
01769         /* Handle as chunk length or chunk data as appropriate */
01770         if ( http->remaining ) {
01771                 return http_rx_chunk_data ( http, iobuf );
01772         } else {
01773                 return http_rx_chunk_len ( http, iobuf );
01774         }
01775 }
01776 
01777 /** Chunked transfer encoding */
01778 struct http_transfer_encoding http_transfer_chunked __http_transfer_encoding = {
01779         .name = "chunked",
01780         .init = http_init_transfer_chunked,
01781         .state = {
01782                 .rx = http_rx_transfer_chunked,
01783                 .close = http_close_error,
01784         },
01785 };
01786 
01787 /******************************************************************************
01788  *
01789  * Response trailers
01790  *
01791  ******************************************************************************
01792  */
01793 
01794 /**
01795  * Handle received HTTP trailer
01796  *
01797  * @v http              HTTP transaction
01798  * @v iobuf             I/O buffer (may be claimed)
01799  * @ret rc              Return status code
01800  */
01801 static int http_rx_trailers ( struct http_transaction *http,
01802                               struct io_buffer **iobuf ) {
01803         char *line;
01804         int rc;
01805 
01806         /* Buffer trailer line */
01807         if ( ( rc = http_rx_linebuf ( http, *iobuf, &http->linebuf ) ) != 0 )
01808                 return rc;
01809 
01810         /* Wait until we see the empty line marking end of trailers */
01811         line = buffered_line ( &http->linebuf );
01812         if ( ( line == NULL ) || ( line[0] != '\0' ) )
01813                 return 0;
01814 
01815         /* Empty line buffer */
01816         empty_line_buffer ( &http->linebuf );
01817 
01818         /* Transfer is complete */
01819         if ( ( rc = http_transfer_complete ( http ) ) != 0 )
01820                 return rc;
01821 
01822         return 0;
01823 }
01824 
01825 /** HTTP response trailers state */
01826 static struct http_state http_trailers = {
01827         .rx = http_rx_trailers,
01828         .close = http_close_error,
01829 };
01830 
01831 /******************************************************************************
01832  *
01833  * Simple URI openers
01834  *
01835  ******************************************************************************
01836  */
01837 
01838 /**
01839  * Construct HTTP parameter list
01840  *
01841  * @v params            Parameter list
01842  * @v buf               Buffer to contain HTTP POST parameters
01843  * @v len               Length of buffer
01844  * @ret len             Length of parameter list (excluding terminating NUL)
01845  */
01846 static size_t http_params ( struct parameters *params, char *buf, size_t len ) {
01847         struct parameter *param;
01848         ssize_t remaining = len;
01849         size_t frag_len;
01850 
01851         /* Add each parameter in the form "key=value", joined with "&" */
01852         len = 0;
01853         for_each_param ( param, params ) {
01854 
01855                 /* Add the "&", if applicable */
01856                 if ( len ) {
01857                         if ( remaining > 0 )
01858                                 *buf = '&';
01859                         buf++;
01860                         len++;
01861                         remaining--;
01862                 }
01863 
01864                 /* URI-encode the key */
01865                 frag_len = uri_encode_string ( 0, param->key, buf, remaining );
01866                 buf += frag_len;
01867                 len += frag_len;
01868                 remaining -= frag_len;
01869 
01870                 /* Add the "=" */
01871                 if ( remaining > 0 )
01872                         *buf = '=';
01873                 buf++;
01874                 len++;
01875                 remaining--;
01876 
01877                 /* URI-encode the value */
01878                 frag_len = uri_encode_string ( 0, param->value, buf, remaining);
01879                 buf += frag_len;
01880                 len += frag_len;
01881                 remaining -= frag_len;
01882         }
01883 
01884         /* Ensure string is NUL-terminated even if no parameters are present */
01885         if ( remaining > 0 )
01886                 *buf = '\0';
01887 
01888         return len;
01889 }
01890 
01891 /**
01892  * Open HTTP transaction for simple GET URI
01893  *
01894  * @v xfer              Data transfer interface
01895  * @v uri               Request URI
01896  * @ret rc              Return status code
01897  */
01898 static int http_open_get_uri ( struct interface *xfer, struct uri *uri ) {
01899 
01900         return http_open ( xfer, &http_get, uri, NULL, NULL );
01901 }
01902 
01903 /**
01904  * Open HTTP transaction for simple POST URI
01905  *
01906  * @v xfer              Data transfer interface
01907  * @v uri               Request URI
01908  * @ret rc              Return status code
01909  */
01910 static int http_open_post_uri ( struct interface *xfer, struct uri *uri ) {
01911         struct parameters *params = uri->params;
01912         struct http_request_content content;
01913         void *data;
01914         size_t len;
01915         size_t check_len;
01916         int rc;
01917 
01918         /* Calculate length of parameter list */
01919         len = http_params ( params, NULL, 0 );
01920 
01921         /* Allocate temporary parameter list */
01922         data = zalloc ( len + 1 /* NUL */ );
01923         if ( ! data ) {
01924                 rc = -ENOMEM;
01925                 goto err_alloc;
01926         }
01927 
01928         /* Construct temporary parameter list */
01929         check_len = http_params ( params, data, ( len + 1 /* NUL */ ) );
01930         assert ( check_len == len );
01931 
01932         /* Construct request content */
01933         content.type = "application/x-www-form-urlencoded";
01934         content.data = data;
01935         content.len = len;
01936 
01937         /* Open HTTP transaction */
01938         if ( ( rc = http_open ( xfer, &http_post, uri, NULL, &content ) ) != 0 )
01939                 goto err_open;
01940 
01941  err_open:
01942         free ( data );
01943  err_alloc:
01944         return rc;
01945 }
01946 
01947 /**
01948  * Open HTTP transaction for simple URI
01949  *
01950  * @v xfer              Data transfer interface
01951  * @v uri               Request URI
01952  * @ret rc              Return status code
01953  */
01954 int http_open_uri ( struct interface *xfer, struct uri *uri ) {
01955 
01956         /* Open GET/POST URI as applicable */
01957         if ( uri->params ) {
01958                 return http_open_post_uri ( xfer, uri );
01959         } else {
01960                 return http_open_get_uri ( xfer, uri );
01961         }
01962 }
01963 
01964 /* Drag in HTTP extensions */
01965 REQUIRING_SYMBOL ( http_open );
01966 REQUIRE_OBJECT ( config_http );