Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / net / tcp / httpcore.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 /**
23  * @file
24  *
25  * Hyper Text Transfer Protocol (HTTP) core functionality
26  *
27  */
28
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <byteswap.h>
35 #include <errno.h>
36 #include <ctype.h>
37 #include <assert.h>
38 #include <ipxe/uri.h>
39 #include <ipxe/refcnt.h>
40 #include <ipxe/iobuf.h>
41 #include <ipxe/xfer.h>
42 #include <ipxe/open.h>
43 #include <ipxe/socket.h>
44 #include <ipxe/tcpip.h>
45 #include <ipxe/process.h>
46 #include <ipxe/retry.h>
47 #include <ipxe/timer.h>
48 #include <ipxe/linebuf.h>
49 #include <ipxe/base64.h>
50 #include <ipxe/base16.h>
51 #include <ipxe/md5.h>
52 #include <ipxe/blockdev.h>
53 #include <ipxe/acpi.h>
54 #include <ipxe/version.h>
55 #include <ipxe/params.h>
56 #include <ipxe/profile.h>
57 #include <ipxe/http.h>
58
59 /* Disambiguate the various error causes */
60 #define EACCES_401 __einfo_error ( EINFO_EACCES_401 )
61 #define EINFO_EACCES_401 \
62         __einfo_uniqify ( EINFO_EACCES, 0x01, "HTTP 401 Unauthorized" )
63 #define EIO_OTHER __einfo_error ( EINFO_EIO_OTHER )
64 #define EINFO_EIO_OTHER \
65         __einfo_uniqify ( EINFO_EIO, 0x01, "Unrecognised HTTP response code" )
66 #define EIO_CONTENT_LENGTH __einfo_error ( EINFO_EIO_CONTENT_LENGTH )
67 #define EINFO_EIO_CONTENT_LENGTH \
68         __einfo_uniqify ( EINFO_EIO, 0x02, "Content length mismatch" )
69 #define EINVAL_RESPONSE __einfo_error ( EINFO_EINVAL_RESPONSE )
70 #define EINFO_EINVAL_RESPONSE \
71         __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid content length" )
72 #define EINVAL_HEADER __einfo_error ( EINFO_EINVAL_HEADER )
73 #define EINFO_EINVAL_HEADER \
74         __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid header" )
75 #define EINVAL_CONTENT_LENGTH __einfo_error ( EINFO_EINVAL_CONTENT_LENGTH )
76 #define EINFO_EINVAL_CONTENT_LENGTH \
77         __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid content length" )
78 #define EINVAL_CHUNK_LENGTH __einfo_error ( EINFO_EINVAL_CHUNK_LENGTH )
79 #define EINFO_EINVAL_CHUNK_LENGTH \
80         __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid chunk length" )
81 #define ENOENT_404 __einfo_error ( EINFO_ENOENT_404 )
82 #define EINFO_ENOENT_404 \
83         __einfo_uniqify ( EINFO_ENOENT, 0x01, "HTTP 404 Not Found" )
84 #define EPERM_403 __einfo_error ( EINFO_EPERM_403 )
85 #define EINFO_EPERM_403 \
86         __einfo_uniqify ( EINFO_EPERM, 0x01, "HTTP 403 Forbidden" )
87 #define EPROTO_UNSOLICITED __einfo_error ( EINFO_EPROTO_UNSOLICITED )
88 #define EINFO_EPROTO_UNSOLICITED \
89         __einfo_uniqify ( EINFO_EPROTO, 0x01, "Unsolicited data" )
90
91 /** Block size used for HTTP block device request */
92 #define HTTP_BLKSIZE 512
93
94 /** Retry delay used when we cannot understand the Retry-After header */
95 #define HTTP_RETRY_SECONDS 5
96
97 /** Receive profiler */
98 static struct profiler http_rx_profiler __profiler = { .name = "http.rx" };
99
100 /** Data transfer profiler */
101 static struct profiler http_xfer_profiler __profiler = { .name = "http.xfer" };
102
103 /** HTTP flags */
104 enum http_flags {
105         /** Request is waiting to be transmitted */
106         HTTP_TX_PENDING = 0x0001,
107         /** Fetch header only */
108         HTTP_HEAD_ONLY = 0x0002,
109         /** Client would like to keep connection alive */
110         HTTP_CLIENT_KEEPALIVE = 0x0004,
111         /** Server will keep connection alive */
112         HTTP_SERVER_KEEPALIVE = 0x0008,
113         /** Discard the current request and try again */
114         HTTP_TRY_AGAIN = 0x0010,
115         /** Provide Basic authentication details */
116         HTTP_BASIC_AUTH = 0x0020,
117         /** Provide Digest authentication details */
118         HTTP_DIGEST_AUTH = 0x0040,
119         /** Socket must be reopened */
120         HTTP_REOPEN_SOCKET = 0x0080,
121 };
122
123 /** HTTP receive state */
124 enum http_rx_state {
125         HTTP_RX_RESPONSE = 0,
126         HTTP_RX_HEADER,
127         HTTP_RX_CHUNK_LEN,
128         /* In HTTP_RX_DATA, it is acceptable for the server to close
129          * the connection (unless we are in the middle of a chunked
130          * transfer).
131          */
132         HTTP_RX_DATA,
133         /* In the following states, it is acceptable for the server to
134          * close the connection.
135          */
136         HTTP_RX_TRAILER,
137         HTTP_RX_IDLE,
138         HTTP_RX_DEAD,
139 };
140
141 /**
142  * An HTTP request
143  *
144  */
145 struct http_request {
146         /** Reference count */
147         struct refcnt refcnt;
148         /** Data transfer interface */
149         struct interface xfer;
150         /** Partial transfer interface */
151         struct interface partial;
152
153         /** URI being fetched */
154         struct uri *uri;
155         /** Default port */
156         unsigned int default_port;
157         /** Filter (if any) */
158         int ( * filter ) ( struct interface *xfer,
159                            const char *name,
160                            struct interface **next );
161         /** Transport layer interface */
162         struct interface socket;
163
164         /** Flags */
165         unsigned int flags;
166         /** Starting offset of partial transfer (if applicable) */
167         size_t partial_start;
168         /** Length of partial transfer (if applicable) */
169         size_t partial_len;
170
171         /** TX process */
172         struct process process;
173
174         /** RX state */
175         enum http_rx_state rx_state;
176         /** Response code */
177         unsigned int code;
178         /** Received length */
179         size_t rx_len;
180         /** Length remaining (or 0 if unknown) */
181         size_t remaining;
182         /** HTTP is using Transfer-Encoding: chunked */
183         int chunked;
184         /** Current chunk length remaining (if applicable) */
185         size_t chunk_remaining;
186         /** Line buffer for received header lines */
187         struct line_buffer linebuf;
188         /** Receive data buffer (if applicable) */
189         userptr_t rx_buffer;
190
191         /** Authentication realm (if any) */
192         char *auth_realm;
193         /** Authentication nonce (if any) */
194         char *auth_nonce;
195         /** Authentication opaque string (if any) */
196         char *auth_opaque;
197
198         /** Request retry timer */
199         struct retry_timer timer;
200         /** Retry delay (in timer ticks) */
201         unsigned long retry_delay;
202 };
203
204 /**
205  * Free HTTP request
206  *
207  * @v refcnt            Reference counter
208  */
209 static void http_free ( struct refcnt *refcnt ) {
210         struct http_request *http =
211                 container_of ( refcnt, struct http_request, refcnt );
212
213         uri_put ( http->uri );
214         empty_line_buffer ( &http->linebuf );
215         free ( http->auth_realm );
216         free ( http->auth_nonce );
217         free ( http->auth_opaque );
218         free ( http );
219 };
220
221 /**
222  * Close HTTP request
223  *
224  * @v http              HTTP request
225  * @v rc                Return status code
226  */
227 static void http_close ( struct http_request *http, int rc ) {
228
229         /* Prevent further processing of any current packet */
230         http->rx_state = HTTP_RX_DEAD;
231
232         /* Prevent reconnection */
233         http->flags &= ~HTTP_CLIENT_KEEPALIVE;
234
235         /* Remove process */
236         process_del ( &http->process );
237
238         /* Close all data transfer interfaces */
239         intf_shutdown ( &http->socket, rc );
240         intf_shutdown ( &http->partial, rc );
241         intf_shutdown ( &http->xfer, rc );
242 }
243
244 /**
245  * Open HTTP socket
246  *
247  * @v http              HTTP request
248  * @ret rc              Return status code
249  */
250 static int http_socket_open ( struct http_request *http ) {
251         struct uri *uri = http->uri;
252         struct sockaddr_tcpip server;
253         struct interface *socket;
254         int rc;
255
256         /* Open socket */
257         memset ( &server, 0, sizeof ( server ) );
258         server.st_port = htons ( uri_port ( uri, http->default_port ) );
259         socket = &http->socket;
260         if ( http->filter ) {
261                 if ( ( rc = http->filter ( socket, uri->host, &socket ) ) != 0 )
262                         return rc;
263         }
264         if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM,
265                                              ( struct sockaddr * ) &server,
266                                              uri->host, NULL ) ) != 0 )
267                 return rc;
268
269         return 0;
270 }
271
272 /**
273  * Retry HTTP request
274  *
275  * @v timer             Retry timer
276  * @v fail              Failure indicator
277  */
278 static void http_retry ( struct retry_timer *timer, int fail __unused ) {
279         struct http_request *http =
280                 container_of ( timer, struct http_request, timer );
281         int rc;
282
283         /* Reopen socket if required */
284         if ( http->flags & HTTP_REOPEN_SOCKET ) {
285                 http->flags &= ~HTTP_REOPEN_SOCKET;
286                 DBGC ( http, "HTTP %p reopening connection\n", http );
287                 if ( ( rc = http_socket_open ( http ) ) != 0 ) {
288                         http_close ( http, rc );
289                         return;
290                 }
291         }
292
293         /* Retry the request if applicable */
294         if ( http->flags & HTTP_TRY_AGAIN ) {
295                 http->flags &= ~HTTP_TRY_AGAIN;
296                 DBGC ( http, "HTTP %p retrying request\n", http );
297                 http->flags |= HTTP_TX_PENDING;
298                 http->rx_state = HTTP_RX_RESPONSE;
299                 process_add ( &http->process );
300         }
301 }
302
303 /**
304  * Mark HTTP request as completed successfully
305  *
306  * @v http              HTTP request
307  */
308 static void http_done ( struct http_request *http ) {
309
310         /* If we are not at an appropriate stage of the protocol
311          * (including being in the middle of a chunked transfer),
312          * force an error.
313          */
314         if ( ( http->rx_state < HTTP_RX_DATA ) || ( http->chunked != 0 ) ) {
315                 DBGC ( http, "HTTP %p connection closed unexpectedly in state "
316                        "%d\n", http, http->rx_state );
317                 http_close ( http, -ECONNRESET );
318                 return;
319         }
320
321         /* If we had a Content-Length, and the received content length
322          * isn't correct, force an error
323          */
324         if ( http->remaining != 0 ) {
325                 DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n",
326                        http, http->rx_len, ( http->rx_len + http->remaining ) );
327                 http_close ( http, -EIO_CONTENT_LENGTH );
328                 return;
329         }
330
331         /* Enter idle state */
332         http->rx_state = HTTP_RX_IDLE;
333         http->rx_len = 0;
334         assert ( http->remaining == 0 );
335         assert ( http->chunked == 0 );
336         assert ( http->chunk_remaining == 0 );
337
338         /* Close partial transfer interface */
339         if ( ! ( http->flags & HTTP_TRY_AGAIN ) )
340                 intf_restart ( &http->partial, 0 );
341
342         /* Close everything unless we want to keep the connection alive */
343         if ( ! ( http->flags & ( HTTP_CLIENT_KEEPALIVE | HTTP_TRY_AGAIN ) ) ) {
344                 http_close ( http, 0 );
345                 return;
346         }
347
348         /* If the server is not intending to keep the connection
349          * alive, then close the socket and mark it as requiring
350          * reopening.
351          */
352         if ( ! ( http->flags & HTTP_SERVER_KEEPALIVE ) ) {
353                 intf_restart ( &http->socket, 0 );
354                 http->flags &= ~HTTP_SERVER_KEEPALIVE;
355                 http->flags |= HTTP_REOPEN_SOCKET;
356         }
357
358         /* Start request retry timer */
359         start_timer_fixed ( &http->timer, http->retry_delay );
360         http->retry_delay = 0;
361 }
362
363 /**
364  * Convert HTTP response code to return status code
365  *
366  * @v response          HTTP response code
367  * @ret rc              Return status code
368  */
369 static int http_response_to_rc ( unsigned int response ) {
370         switch ( response ) {
371         case 200:
372         case 206:
373         case 301:
374         case 302:
375         case 303:
376                 return 0;
377         case 404:
378                 return -ENOENT_404;
379         case 403:
380                 return -EPERM_403;
381         case 401:
382                 return -EACCES_401;
383         default:
384                 return -EIO_OTHER;
385         }
386 }
387
388 /**
389  * Handle HTTP response
390  *
391  * @v http              HTTP request
392  * @v response          HTTP response
393  * @ret rc              Return status code
394  */
395 static int http_rx_response ( struct http_request *http, char *response ) {
396         char *spc;
397
398         DBGC ( http, "HTTP %p response \"%s\"\n", http, response );
399
400         /* Check response starts with "HTTP/" */
401         if ( strncmp ( response, "HTTP/", 5 ) != 0 )
402                 return -EINVAL_RESPONSE;
403
404         /* Locate and store response code */
405         spc = strchr ( response, ' ' );
406         if ( ! spc )
407                 return -EINVAL_RESPONSE;
408         http->code = strtoul ( spc, NULL, 10 );
409
410         /* Move to receive headers */
411         http->rx_state = ( ( http->flags & HTTP_HEAD_ONLY ) ?
412                            HTTP_RX_TRAILER : HTTP_RX_HEADER );
413         return 0;
414 }
415
416 /**
417  * Handle HTTP Location header
418  *
419  * @v http              HTTP request
420  * @v value             HTTP header value
421  * @ret rc              Return status code
422  */
423 static int http_rx_location ( struct http_request *http, char *value ) {
424         int rc;
425
426         /* Redirect to new location */
427         DBGC ( http, "HTTP %p redirecting to %s\n", http, value );
428         if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI_STRING,
429                                     value ) ) != 0 ) {
430                 DBGC ( http, "HTTP %p could not redirect: %s\n",
431                        http, strerror ( rc ) );
432                 return rc;
433         }
434
435         return 0;
436 }
437
438 /**
439  * Handle HTTP Content-Length header
440  *
441  * @v http              HTTP request
442  * @v value             HTTP header value
443  * @ret rc              Return status code
444  */
445 static int http_rx_content_length ( struct http_request *http, char *value ) {
446         struct block_device_capacity capacity;
447         size_t content_len;
448         char *endp;
449
450         /* Parse content length */
451         content_len = strtoul ( value, &endp, 10 );
452         if ( ! ( ( *endp == '\0' ) || isspace ( *endp ) ) ) {
453                 DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n",
454                        http, value );
455                 return -EINVAL_CONTENT_LENGTH;
456         }
457
458         /* If we already have an expected content length, and this
459          * isn't it, then complain
460          */
461         if ( http->remaining && ( http->remaining != content_len ) ) {
462                 DBGC ( http, "HTTP %p incorrect Content-Length %zd (expected "
463                        "%zd)\n", http, content_len, http->remaining );
464                 return -EIO_CONTENT_LENGTH;
465         }
466         if ( ! ( http->flags & HTTP_HEAD_ONLY ) )
467                 http->remaining = content_len;
468
469         /* Do nothing more if we are retrying the request */
470         if ( http->flags & HTTP_TRY_AGAIN )
471                 return 0;
472
473         /* Use seek() to notify recipient of filesize */
474         xfer_seek ( &http->xfer, http->remaining );
475         xfer_seek ( &http->xfer, 0 );
476
477         /* Report block device capacity if applicable */
478         if ( http->flags & HTTP_HEAD_ONLY ) {
479                 capacity.blocks = ( content_len / HTTP_BLKSIZE );
480                 capacity.blksize = HTTP_BLKSIZE;
481                 capacity.max_count = -1U;
482                 block_capacity ( &http->partial, &capacity );
483         }
484         return 0;
485 }
486
487 /**
488  * Handle HTTP Transfer-Encoding header
489  *
490  * @v http              HTTP request
491  * @v value             HTTP header value
492  * @ret rc              Return status code
493  */
494 static int http_rx_transfer_encoding ( struct http_request *http, char *value ){
495
496         if ( strcasecmp ( value, "chunked" ) == 0 ) {
497                 /* Mark connection as using chunked transfer encoding */
498                 http->chunked = 1;
499         }
500
501         return 0;
502 }
503
504 /**
505  * Handle HTTP Connection header
506  *
507  * @v http              HTTP request
508  * @v value             HTTP header value
509  * @ret rc              Return status code
510  */
511 static int http_rx_connection ( struct http_request *http, char *value ) {
512
513         if ( strcasecmp ( value, "keep-alive" ) == 0 ) {
514                 /* Mark connection as being kept alive by the server */
515                 http->flags |= HTTP_SERVER_KEEPALIVE;
516         }
517
518         return 0;
519 }
520
521 /**
522  * Handle WWW-Authenticate Basic header
523  *
524  * @v http              HTTP request
525  * @v params            Parameters
526  * @ret rc              Return status code
527  */
528 static int http_rx_basic_auth ( struct http_request *http, char *params ) {
529
530         DBGC ( http, "HTTP %p Basic authentication required (%s)\n",
531                http, params );
532
533         /* If we received a 401 Unauthorized response, then retry
534          * using Basic authentication
535          */
536         if ( ( http->code == 401 ) &&
537              ( ! ( http->flags & HTTP_BASIC_AUTH ) ) &&
538              ( http->uri->user != NULL ) ) {
539                 http->flags |= ( HTTP_TRY_AGAIN | HTTP_BASIC_AUTH );
540         }
541
542         return 0;
543 }
544
545 /**
546  * Parse Digest authentication parameter
547  *
548  * @v params            Parameters
549  * @v name              Parameter name (including trailing "=\"")
550  * @ret value           Parameter value, or NULL
551  */
552 static char * http_digest_param ( char *params, const char *name ) {
553         char *key;
554         char *value;
555         char *terminator;
556
557         /* Locate parameter */
558         key = strstr ( params, name );
559         if ( ! key )
560                 return NULL;
561
562         /* Extract value */
563         value = ( key + strlen ( name ) );
564         terminator = strchr ( value, '"' );
565         if ( ! terminator )
566                 return NULL;
567         return strndup ( value, ( terminator - value ) );
568 }
569
570 /**
571  * Handle WWW-Authenticate Digest header
572  *
573  * @v http              HTTP request
574  * @v params            Parameters
575  * @ret rc              Return status code
576  */
577 static int http_rx_digest_auth ( struct http_request *http, char *params ) {
578
579         DBGC ( http, "HTTP %p Digest authentication required (%s)\n",
580                http, params );
581
582         /* If we received a 401 Unauthorized response, then retry
583          * using Digest authentication
584          */
585         if ( ( http->code == 401 ) &&
586              ( ! ( http->flags & HTTP_DIGEST_AUTH ) ) &&
587              ( http->uri->user != NULL ) ) {
588
589                 /* Extract realm */
590                 free ( http->auth_realm );
591                 http->auth_realm = http_digest_param ( params, "realm=\"" );
592                 if ( ! http->auth_realm ) {
593                         DBGC ( http, "HTTP %p Digest prompt missing realm\n",
594                                http );
595                         return -EINVAL_HEADER;
596                 }
597
598                 /* Extract nonce */
599                 free ( http->auth_nonce );
600                 http->auth_nonce = http_digest_param ( params, "nonce=\"" );
601                 if ( ! http->auth_nonce ) {
602                         DBGC ( http, "HTTP %p Digest prompt missing nonce\n",
603                                http );
604                         return -EINVAL_HEADER;
605                 }
606
607                 /* Extract opaque */
608                 free ( http->auth_opaque );
609                 http->auth_opaque = http_digest_param ( params, "opaque=\"" );
610                 if ( ! http->auth_opaque ) {
611                         /* Not an error; "opaque" is optional */
612                 }
613
614                 http->flags |= ( HTTP_TRY_AGAIN | HTTP_DIGEST_AUTH );
615         }
616
617         return 0;
618 }
619
620 /** An HTTP WWW-Authenticate header handler */
621 struct http_auth_header_handler {
622         /** Scheme (e.g. "Basic") */
623         const char *scheme;
624         /** Handle received parameters
625          *
626          * @v http      HTTP request
627          * @v params    Parameters
628          * @ret rc      Return status code
629          */
630         int ( * rx ) ( struct http_request *http, char *params );
631 };
632
633 /** List of HTTP WWW-Authenticate header handlers */
634 static struct http_auth_header_handler http_auth_header_handlers[] = {
635         {
636                 .scheme = "Basic",
637                 .rx = http_rx_basic_auth,
638         },
639         {
640                 .scheme = "Digest",
641                 .rx = http_rx_digest_auth,
642         },
643         { NULL, NULL },
644 };
645
646 /**
647  * Handle HTTP WWW-Authenticate header
648  *
649  * @v http              HTTP request
650  * @v value             HTTP header value
651  * @ret rc              Return status code
652  */
653 static int http_rx_www_authenticate ( struct http_request *http, char *value ) {
654         struct http_auth_header_handler *handler;
655         char *separator;
656         char *scheme;
657         char *params;
658         int rc;
659
660         /* Extract scheme */
661         separator = strchr ( value, ' ' );
662         if ( ! separator ) {
663                 DBGC ( http, "HTTP %p malformed WWW-Authenticate header\n",
664                        http );
665                 return -EINVAL_HEADER;
666         }
667         *separator = '\0';
668         scheme = value;
669         params = ( separator + 1 );
670
671         /* Hand off to header handler, if one exists */
672         for ( handler = http_auth_header_handlers; handler->scheme; handler++ ){
673                 if ( strcasecmp ( scheme, handler->scheme ) == 0 ) {
674                         if ( ( rc = handler->rx ( http, params ) ) != 0 )
675                                 return rc;
676                         break;
677                 }
678         }
679         return 0;
680 }
681
682 /**
683  * Handle HTTP Retry-After header
684  *
685  * @v http              HTTP request
686  * @v value             HTTP header value
687  * @ret rc              Return status code
688  */
689 static int http_rx_retry_after ( struct http_request *http, char *value ) {
690         unsigned long seconds;
691         char *endp;
692
693         DBGC ( http, "HTTP %p retry requested (%s)\n", http, value );
694
695         /* If we received a 503 Service Unavailable response, then
696          * retry after the specified number of seconds.  If the value
697          * is not a simple number of seconds (e.g. a full HTTP date),
698          * then retry after a fixed delay, since we don't have code
699          * able to parse full HTTP dates.
700          */
701         if ( http->code == 503 ) {
702                 seconds = strtoul ( value, &endp, 10 );
703                 if ( *endp != '\0' ) {
704                         seconds = HTTP_RETRY_SECONDS;
705                         DBGC ( http, "HTTP %p cannot understand \"%s\"; "
706                                "using %ld seconds\n", http, value, seconds );
707                 }
708                 http->flags |= HTTP_TRY_AGAIN;
709                 http->retry_delay = ( seconds * TICKS_PER_SEC );
710         }
711
712         return 0;
713 }
714
715 /** An HTTP header handler */
716 struct http_header_handler {
717         /** Name (e.g. "Content-Length") */
718         const char *header;
719         /** Handle received header
720          *
721          * @v http      HTTP request
722          * @v value     HTTP header value
723          * @ret rc      Return status code
724          *
725          * If an error is returned, the download will be aborted.
726          */
727         int ( * rx ) ( struct http_request *http, char *value );
728 };
729
730 /** List of HTTP header handlers */
731 static struct http_header_handler http_header_handlers[] = {
732         {
733                 .header = "Location",
734                 .rx = http_rx_location,
735         },
736         {
737                 .header = "Content-Length",
738                 .rx = http_rx_content_length,
739         },
740         {
741                 .header = "Transfer-Encoding",
742                 .rx = http_rx_transfer_encoding,
743         },
744         {
745                 .header = "Connection",
746                 .rx = http_rx_connection,
747         },
748         {
749                 .header = "WWW-Authenticate",
750                 .rx = http_rx_www_authenticate,
751         },
752         {
753                 .header = "Retry-After",
754                 .rx = http_rx_retry_after,
755         },
756         { NULL, NULL }
757 };
758
759 /**
760  * Handle HTTP header
761  *
762  * @v http              HTTP request
763  * @v header            HTTP header
764  * @ret rc              Return status code
765  */
766 static int http_rx_header ( struct http_request *http, char *header ) {
767         struct http_header_handler *handler;
768         char *separator;
769         char *value;
770         int rc;
771
772         /* An empty header line marks the end of this phase */
773         if ( ! header[0] ) {
774                 empty_line_buffer ( &http->linebuf );
775
776                 /* Handle response code */
777                 if ( ! ( http->flags & HTTP_TRY_AGAIN ) ) {
778                         if ( ( rc = http_response_to_rc ( http->code ) ) != 0 )
779                                 return rc;
780                 }
781
782                 /* Move to next state */
783                 if ( http->rx_state == HTTP_RX_HEADER ) {
784                         DBGC ( http, "HTTP %p start of data\n", http );
785                         http->rx_state = ( http->chunked ?
786                                            HTTP_RX_CHUNK_LEN : HTTP_RX_DATA );
787                         if ( ( http->partial_len != 0 ) &&
788                              ( ! ( http->flags & HTTP_TRY_AGAIN ) ) ) {
789                                 http->remaining = http->partial_len;
790                         }
791                         return 0;
792                 } else {
793                         DBGC ( http, "HTTP %p end of trailer\n", http );
794                         http_done ( http );
795                         return 0;
796                 }
797         }
798
799         DBGC ( http, "HTTP %p header \"%s\"\n", http, header );
800
801         /* Split header at the ": " */
802         separator = strstr ( header, ": " );
803         if ( ! separator ) {
804                 DBGC ( http, "HTTP %p malformed header\n", http );
805                 return -EINVAL_HEADER;
806         }
807         *separator = '\0';
808         value = ( separator + 2 );
809
810         /* Hand off to header handler, if one exists */
811         for ( handler = http_header_handlers ; handler->header ; handler++ ) {
812                 if ( strcasecmp ( header, handler->header ) == 0 ) {
813                         if ( ( rc = handler->rx ( http, value ) ) != 0 )
814                                 return rc;
815                         break;
816                 }
817         }
818         return 0;
819 }
820
821 /**
822  * Handle HTTP chunk length
823  *
824  * @v http              HTTP request
825  * @v length            HTTP chunk length
826  * @ret rc              Return status code
827  */
828 static int http_rx_chunk_len ( struct http_request *http, char *length ) {
829         char *endp;
830
831         /* Skip blank lines between chunks */
832         if ( length[0] == '\0' )
833                 return 0;
834
835         /* Parse chunk length */
836         http->chunk_remaining = strtoul ( length, &endp, 16 );
837         if ( *endp != '\0' ) {
838                 DBGC ( http, "HTTP %p invalid chunk length \"%s\"\n",
839                        http, length );
840                 return -EINVAL_CHUNK_LENGTH;
841         }
842
843         /* Terminate chunked encoding if applicable */
844         if ( http->chunk_remaining == 0 ) {
845                 DBGC ( http, "HTTP %p end of chunks\n", http );
846                 http->chunked = 0;
847                 http->rx_state = HTTP_RX_TRAILER;
848                 return 0;
849         }
850
851         /* Use seek() to notify recipient of new filesize */
852         DBGC ( http, "HTTP %p start of chunk of length %zd\n",
853                http, http->chunk_remaining );
854         if ( ! ( http->flags & HTTP_TRY_AGAIN ) ) {
855                 xfer_seek ( &http->xfer,
856                             ( http->rx_len + http->chunk_remaining ) );
857                 xfer_seek ( &http->xfer, http->rx_len );
858         }
859
860         /* Start receiving data */
861         http->rx_state = HTTP_RX_DATA;
862
863         return 0;
864 }
865
866 /** An HTTP line-based data handler */
867 struct http_line_handler {
868         /** Handle line
869          *
870          * @v http      HTTP request
871          * @v line      Line to handle
872          * @ret rc      Return status code
873          */
874         int ( * rx ) ( struct http_request *http, char *line );
875 };
876
877 /** List of HTTP line-based data handlers */
878 static struct http_line_handler http_line_handlers[] = {
879         [HTTP_RX_RESPONSE]      = { .rx = http_rx_response },
880         [HTTP_RX_HEADER]        = { .rx = http_rx_header },
881         [HTTP_RX_CHUNK_LEN]     = { .rx = http_rx_chunk_len },
882         [HTTP_RX_TRAILER]       = { .rx = http_rx_header },
883 };
884
885 /**
886  * Handle new data arriving via HTTP connection
887  *
888  * @v http              HTTP request
889  * @v iobuf             I/O buffer
890  * @v meta              Data transfer metadata
891  * @ret rc              Return status code
892  */
893 static int http_socket_deliver ( struct http_request *http,
894                                  struct io_buffer *iobuf,
895                                  struct xfer_metadata *meta __unused ) {
896         struct http_line_handler *lh;
897         char *line;
898         size_t data_len;
899         ssize_t line_len;
900         int rc = 0;
901
902         profile_start ( &http_rx_profiler );
903         while ( iobuf && iob_len ( iobuf ) ) {
904
905                 switch ( http->rx_state ) {
906                 case HTTP_RX_IDLE:
907                         /* Receiving any data in this state is an error */
908                         DBGC ( http, "HTTP %p received %zd bytes while %s\n",
909                                http, iob_len ( iobuf ),
910                                ( ( http->rx_state == HTTP_RX_IDLE ) ?
911                                  "idle" : "dead" ) );
912                         rc = -EPROTO_UNSOLICITED;
913                         goto done;
914                 case HTTP_RX_DEAD:
915                         /* Do no further processing */
916                         goto done;
917                 case HTTP_RX_DATA:
918                         /* Pass received data to caller */
919                         data_len = iob_len ( iobuf );
920                         if ( http->chunk_remaining &&
921                              ( http->chunk_remaining < data_len ) ) {
922                                 data_len = http->chunk_remaining;
923                         }
924                         if ( http->remaining &&
925                              ( http->remaining < data_len ) ) {
926                                 data_len = http->remaining;
927                         }
928                         if ( http->flags & HTTP_TRY_AGAIN ) {
929                                 /* Discard all received data */
930                                 iob_pull ( iobuf, data_len );
931                         } else if ( http->rx_buffer != UNULL ) {
932                                 /* Copy to partial transfer buffer */
933                                 copy_to_user ( http->rx_buffer, http->rx_len,
934                                                iobuf->data, data_len );
935                                 iob_pull ( iobuf, data_len );
936                         } else if ( data_len < iob_len ( iobuf ) ) {
937                                 /* Deliver partial buffer as raw data */
938                                 profile_start ( &http_xfer_profiler );
939                                 rc = xfer_deliver_raw ( &http->xfer,
940                                                         iobuf->data, data_len );
941                                 iob_pull ( iobuf, data_len );
942                                 if ( rc != 0 )
943                                         goto done;
944                                 profile_stop ( &http_xfer_profiler );
945                         } else {
946                                 /* Deliver whole I/O buffer */
947                                 profile_start ( &http_xfer_profiler );
948                                 if ( ( rc = xfer_deliver_iob ( &http->xfer,
949                                                  iob_disown ( iobuf ) ) ) != 0 )
950                                         goto done;
951                                 profile_stop ( &http_xfer_profiler );
952                         }
953                         http->rx_len += data_len;
954                         if ( http->chunk_remaining ) {
955                                 http->chunk_remaining -= data_len;
956                                 if ( http->chunk_remaining == 0 )
957                                         http->rx_state = HTTP_RX_CHUNK_LEN;
958                         }
959                         if ( http->remaining ) {
960                                 http->remaining -= data_len;
961                                 if ( ( http->remaining == 0 ) &&
962                                      ( http->rx_state == HTTP_RX_DATA ) ) {
963                                         http_done ( http );
964                                 }
965                         }
966                         break;
967                 case HTTP_RX_RESPONSE:
968                 case HTTP_RX_HEADER:
969                 case HTTP_RX_CHUNK_LEN:
970                 case HTTP_RX_TRAILER:
971                         /* In the other phases, buffer and process a
972                          * line at a time
973                          */
974                         line_len = line_buffer ( &http->linebuf, iobuf->data,
975                                                  iob_len ( iobuf ) );
976                         if ( line_len < 0 ) {
977                                 rc = line_len;
978                                 DBGC ( http, "HTTP %p could not buffer line: "
979                                        "%s\n", http, strerror ( rc ) );
980                                 goto done;
981                         }
982                         iob_pull ( iobuf, line_len );
983                         line = buffered_line ( &http->linebuf );
984                         if ( line ) {
985                                 lh = &http_line_handlers[http->rx_state];
986                                 if ( ( rc = lh->rx ( http, line ) ) != 0 )
987                                         goto done;
988                         }
989                         break;
990                 default:
991                         assert ( 0 );
992                         break;
993                 }
994         }
995
996  done:
997         if ( rc )
998                 http_close ( http, rc );
999         free_iob ( iobuf );
1000         profile_stop ( &http_rx_profiler );
1001         return rc;
1002 }
1003
1004 /**
1005  * Check HTTP socket flow control window
1006  *
1007  * @v http              HTTP request
1008  * @ret len             Length of window
1009  */
1010 static size_t http_socket_window ( struct http_request *http __unused ) {
1011
1012         /* Window is always open.  This is to prevent TCP from
1013          * stalling if our parent window is not currently open.
1014          */
1015         return ( ~( ( size_t ) 0 ) );
1016 }
1017
1018 /**
1019  * Close HTTP socket
1020  *
1021  * @v http              HTTP request
1022  * @v rc                Reason for close
1023  */
1024 static void http_socket_close ( struct http_request *http, int rc ) {
1025
1026         /* If we have an error, terminate */
1027         if ( rc != 0 ) {
1028                 http_close ( http, rc );
1029                 return;
1030         }
1031
1032         /* Mark HTTP request as complete */
1033         http_done ( http );
1034 }
1035
1036 /**
1037  * Generate HTTP Basic authorisation string
1038  *
1039  * @v http              HTTP request
1040  * @ret auth            Authorisation string, or NULL on error
1041  *
1042  * The authorisation string is dynamically allocated, and must be
1043  * freed by the caller.
1044  */
1045 static char * http_basic_auth ( struct http_request *http ) {
1046         const char *user = http->uri->user;
1047         const char *password = ( http->uri->password ?
1048                                  http->uri->password : "" );
1049         size_t user_pw_len =
1050                 ( strlen ( user ) + 1 /* ":" */ + strlen ( password ) );
1051         char user_pw[ user_pw_len + 1 /* NUL */ ];
1052         size_t user_pw_base64_len = base64_encoded_len ( user_pw_len );
1053         char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
1054         char *auth;
1055         int len;
1056
1057         /* Sanity check */
1058         assert ( user != NULL );
1059
1060         /* Make "user:password" string from decoded fields */
1061         snprintf ( user_pw, sizeof ( user_pw ), "%s:%s", user, password );
1062
1063         /* Base64-encode the "user:password" string */
1064         base64_encode ( ( void * ) user_pw, user_pw_len, user_pw_base64 );
1065
1066         /* Generate the authorisation string */
1067         len = asprintf ( &auth, "Authorization: Basic %s\r\n",
1068                          user_pw_base64 );
1069         if ( len < 0 )
1070                 return NULL;
1071
1072         return auth;
1073 }
1074
1075 /**
1076  * Generate HTTP Digest authorisation string
1077  *
1078  * @v http              HTTP request
1079  * @v method            HTTP method (e.g. "GET")
1080  * @v uri               HTTP request URI (e.g. "/index.html")
1081  * @ret auth            Authorisation string, or NULL on error
1082  *
1083  * The authorisation string is dynamically allocated, and must be
1084  * freed by the caller.
1085  */
1086 static char * http_digest_auth ( struct http_request *http,
1087                                  const char *method, const char *uri ) {
1088         const char *user = http->uri->user;
1089         const char *password = ( http->uri->password ?
1090                                  http->uri->password : "" );
1091         const char *realm = http->auth_realm;
1092         const char *nonce = http->auth_nonce;
1093         const char *opaque = http->auth_opaque;
1094         static const char colon = ':';
1095         uint8_t ctx[MD5_CTX_SIZE];
1096         uint8_t digest[MD5_DIGEST_SIZE];
1097         char ha1[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ];
1098         char ha2[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ];
1099         char response[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ];
1100         char *auth;
1101         int len;
1102
1103         /* Sanity checks */
1104         assert ( user != NULL );
1105         assert ( realm != NULL );
1106         assert ( nonce != NULL );
1107
1108         /* Generate HA1 */
1109         digest_init ( &md5_algorithm, ctx );
1110         digest_update ( &md5_algorithm, ctx, user, strlen ( user ) );
1111         digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) );
1112         digest_update ( &md5_algorithm, ctx, realm, strlen ( realm ) );
1113         digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) );
1114         digest_update ( &md5_algorithm, ctx, password, strlen ( password ) );
1115         digest_final ( &md5_algorithm, ctx, digest );
1116         base16_encode ( digest, sizeof ( digest ), ha1 );
1117
1118         /* Generate HA2 */
1119         digest_init ( &md5_algorithm, ctx );
1120         digest_update ( &md5_algorithm, ctx, method, strlen ( method ) );
1121         digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) );
1122         digest_update ( &md5_algorithm, ctx, uri, strlen ( uri ) );
1123         digest_final ( &md5_algorithm, ctx, digest );
1124         base16_encode ( digest, sizeof ( digest ), ha2 );
1125
1126         /* Generate response */
1127         digest_init ( &md5_algorithm, ctx );
1128         digest_update ( &md5_algorithm, ctx, ha1, strlen ( ha1 ) );
1129         digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) );
1130         digest_update ( &md5_algorithm, ctx, nonce, strlen ( nonce ) );
1131         digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) );
1132         digest_update ( &md5_algorithm, ctx, ha2, strlen ( ha2 ) );
1133         digest_final ( &md5_algorithm, ctx, digest );
1134         base16_encode ( digest, sizeof ( digest ), response );
1135
1136         /* Generate the authorisation string */
1137         len = asprintf ( &auth, "Authorization: Digest username=\"%s\", "
1138                          "realm=\"%s\", nonce=\"%s\", uri=\"%s\", "
1139                          "%s%s%sresponse=\"%s\"\r\n", user, realm, nonce, uri,
1140                          ( opaque ? "opaque=\"" : "" ),
1141                          ( opaque ? opaque : "" ),
1142                          ( opaque ? "\", " : "" ), response );
1143         if ( len < 0 )
1144                 return NULL;
1145
1146         return auth;
1147 }
1148
1149 /**
1150  * Generate HTTP POST parameter list
1151  *
1152  * @v http              HTTP request
1153  * @v buf               Buffer to contain HTTP POST parameters
1154  * @v len               Length of buffer
1155  * @ret len             Length of parameter list (excluding terminating NUL)
1156  */
1157 static size_t http_post_params ( struct http_request *http,
1158                                  char *buf, size_t len ) {
1159         struct parameter *param;
1160         ssize_t remaining = len;
1161         size_t frag_len;
1162
1163         /* Add each parameter in the form "key=value", joined with "&" */
1164         len = 0;
1165         for_each_param ( param, http->uri->params ) {
1166
1167                 /* Add the "&", if applicable */
1168                 if ( len ) {
1169                         if ( remaining > 0 )
1170                                 *buf = '&';
1171                         buf++;
1172                         len++;
1173                         remaining--;
1174                 }
1175
1176                 /* URI-encode the key */
1177                 frag_len = uri_encode ( param->key, 0, buf, remaining );
1178                 buf += frag_len;
1179                 len += frag_len;
1180                 remaining -= frag_len;
1181
1182                 /* Add the "=" */
1183                 if ( remaining > 0 )
1184                         *buf = '=';
1185                 buf++;
1186                 len++;
1187                 remaining--;
1188
1189                 /* URI-encode the value */
1190                 frag_len = uri_encode ( param->value, 0, buf, remaining );
1191                 buf += frag_len;
1192                 len += frag_len;
1193                 remaining -= frag_len;
1194         }
1195
1196         /* Ensure string is NUL-terminated even if no parameters are present */
1197         if ( remaining > 0 )
1198                 *buf = '\0';
1199
1200         return len;
1201 }
1202
1203 /**
1204  * Generate HTTP POST body
1205  *
1206  * @v http              HTTP request
1207  * @ret post            I/O buffer containing POST body, or NULL on error
1208  */
1209 static struct io_buffer * http_post ( struct http_request *http ) {
1210         struct io_buffer *post;
1211         size_t len;
1212         size_t check_len;
1213
1214         /* Calculate length of parameter list */
1215         len = http_post_params ( http, NULL, 0 );
1216
1217         /* Allocate parameter list */
1218         post = alloc_iob ( len + 1 /* NUL */ );
1219         if ( ! post )
1220                 return NULL;
1221
1222         /* Fill parameter list */
1223         check_len = http_post_params ( http, iob_put ( post, len ),
1224                                        ( len + 1 /* NUL */ ) );
1225         assert ( len == check_len );
1226         DBGC ( http, "HTTP %p POST %s\n", http, ( ( char * ) post->data ) );
1227
1228         return post;
1229 }
1230
1231 /**
1232  * HTTP process
1233  *
1234  * @v http              HTTP request
1235  */
1236 static void http_step ( struct http_request *http ) {
1237         struct io_buffer *post;
1238         struct uri host_uri;
1239         struct uri path_uri;
1240         char *host_uri_string;
1241         char *path_uri_string;
1242         char *method;
1243         char *range;
1244         char *auth;
1245         char *content;
1246         int len;
1247         int rc;
1248
1249         /* Do nothing if we have already transmitted the request */
1250         if ( ! ( http->flags & HTTP_TX_PENDING ) )
1251                 return;
1252
1253         /* Do nothing until socket is ready */
1254         if ( ! xfer_window ( &http->socket ) )
1255                 return;
1256
1257         /* Force a HEAD request if we have nowhere to send any received data */
1258         if ( ( xfer_window ( &http->xfer ) == 0 ) &&
1259              ( http->rx_buffer == UNULL ) ) {
1260                 http->flags |= ( HTTP_HEAD_ONLY | HTTP_CLIENT_KEEPALIVE );
1261         }
1262
1263         /* Determine method */
1264         method = ( ( http->flags & HTTP_HEAD_ONLY ) ? "HEAD" :
1265                    ( http->uri->params ? "POST" : "GET" ) );
1266
1267         /* Construct host URI */
1268         memset ( &host_uri, 0, sizeof ( host_uri ) );
1269         host_uri.host = http->uri->host;
1270         host_uri.port = http->uri->port;
1271         host_uri_string = format_uri_alloc ( &host_uri );
1272         if ( ! host_uri_string ) {
1273                 rc = -ENOMEM;
1274                 goto err_host_uri;
1275         }
1276
1277         /* Construct path URI */
1278         memset ( &path_uri, 0, sizeof ( path_uri ) );
1279         path_uri.path = ( http->uri->path ? http->uri->path : "/" );
1280         path_uri.query = http->uri->query;
1281         path_uri_string = format_uri_alloc ( &path_uri );
1282         if ( ! path_uri_string ) {
1283                 rc = -ENOMEM;
1284                 goto err_path_uri;
1285         }
1286
1287         /* Calculate range request parameters if applicable */
1288         if ( http->partial_len ) {
1289                 len = asprintf ( &range, "Range: bytes=%zd-%zd\r\n",
1290                                  http->partial_start,
1291                                  ( http->partial_start + http->partial_len
1292                                    - 1 ) );
1293                 if ( len < 0 ) {
1294                         rc = len;
1295                         goto err_range;
1296                 }
1297         } else {
1298                 range = NULL;
1299         }
1300
1301         /* Construct authorisation, if applicable */
1302         if ( http->flags & HTTP_BASIC_AUTH ) {
1303                 auth = http_basic_auth ( http );
1304                 if ( ! auth ) {
1305                         rc = -ENOMEM;
1306                         goto err_auth;
1307                 }
1308         } else if ( http->flags & HTTP_DIGEST_AUTH ) {
1309                 auth = http_digest_auth ( http, method, path_uri_string );
1310                 if ( ! auth ) {
1311                         rc = -ENOMEM;
1312                         goto err_auth;
1313                 }
1314         } else {
1315                 auth = NULL;
1316         }
1317
1318         /* Construct POST content, if applicable */
1319         if ( http->uri->params ) {
1320                 post = http_post ( http );
1321                 if ( ! post ) {
1322                         rc = -ENOMEM;
1323                         goto err_post;
1324                 }
1325                 len = asprintf ( &content, "Content-Type: "
1326                                  "application/x-www-form-urlencoded\r\n"
1327                                  "Content-Length: %zd\r\n", iob_len ( post ) );
1328                 if ( len < 0 ) {
1329                         rc = len;
1330                         goto err_content;
1331                 }
1332         } else {
1333                 post = NULL;
1334                 content = NULL;
1335         }
1336
1337         /* Mark request as transmitted */
1338         http->flags &= ~HTTP_TX_PENDING;
1339
1340         /* Send request */
1341         if ( ( rc = xfer_printf ( &http->socket,
1342                                   "%s %s HTTP/1.1\r\n"
1343                                   "User-Agent: iPXE/%s\r\n"
1344                                   "Host: %s\r\n"
1345                                   "%s%s%s%s"
1346                                   "\r\n",
1347                                   method, path_uri_string, product_version,
1348                                   host_uri_string,
1349                                   ( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ?
1350                                     "Connection: keep-alive\r\n" : "" ),
1351                                   ( range ? range : "" ),
1352                                   ( auth ? auth : "" ),
1353                                   ( content ? content : "" ) ) ) != 0 ) {
1354                 goto err_xfer;
1355         }
1356
1357         /* Send POST content, if applicable */
1358         if ( post ) {
1359                 if ( ( rc = xfer_deliver_iob ( &http->socket,
1360                                                iob_disown ( post ) ) ) != 0 )
1361                         goto err_xfer_post;
1362         }
1363
1364  err_xfer_post:
1365  err_xfer:
1366         free ( content );
1367  err_content:
1368         free ( post );
1369  err_post:
1370         free ( auth );
1371  err_auth:
1372         free ( range );
1373  err_range:
1374         free ( path_uri_string );
1375  err_path_uri:
1376         free ( host_uri_string );
1377  err_host_uri:
1378         if ( rc != 0 )
1379                 http_close ( http, rc );
1380 }
1381
1382 /**
1383  * Check HTTP data transfer flow control window
1384  *
1385  * @v http              HTTP request
1386  * @ret len             Length of window
1387  */
1388 static size_t http_xfer_window ( struct http_request *http ) {
1389
1390         /* New block commands may be issued only when we are idle */
1391         return ( ( http->rx_state == HTTP_RX_IDLE ) ? 1 : 0 );
1392 }
1393
1394 /**
1395  * Initiate HTTP partial read
1396  *
1397  * @v http              HTTP request
1398  * @v partial           Partial transfer interface
1399  * @v offset            Starting offset
1400  * @v buffer            Data buffer
1401  * @v len               Length
1402  * @ret rc              Return status code
1403  */
1404 static int http_partial_read ( struct http_request *http,
1405                                struct interface *partial,
1406                                size_t offset, userptr_t buffer, size_t len ) {
1407
1408         /* Sanity check */
1409         if ( http_xfer_window ( http ) == 0 )
1410                 return -EBUSY;
1411
1412         /* Initialise partial transfer parameters */
1413         http->rx_buffer = buffer;
1414         http->partial_start = offset;
1415         http->partial_len = len;
1416
1417         /* Schedule request */
1418         http->rx_state = HTTP_RX_RESPONSE;
1419         http->flags = ( HTTP_TX_PENDING | HTTP_CLIENT_KEEPALIVE );
1420         if ( ! len )
1421                 http->flags |= HTTP_HEAD_ONLY;
1422         process_add ( &http->process );
1423
1424         /* Attach to parent interface and return */
1425         intf_plug_plug ( &http->partial, partial );
1426
1427         return 0;
1428 }
1429
1430 /**
1431  * Issue HTTP block device read
1432  *
1433  * @v http              HTTP request
1434  * @v block             Block data interface
1435  * @v lba               Starting logical block address
1436  * @v count             Number of blocks to transfer
1437  * @v buffer            Data buffer
1438  * @v len               Length of data buffer
1439  * @ret rc              Return status code
1440  */
1441 static int http_block_read ( struct http_request *http,
1442                              struct interface *block,
1443                              uint64_t lba, unsigned int count,
1444                              userptr_t buffer, size_t len __unused ) {
1445
1446         return http_partial_read ( http, block, ( lba * HTTP_BLKSIZE ),
1447                                    buffer, ( count * HTTP_BLKSIZE ) );
1448 }
1449
1450 /**
1451  * Read HTTP block device capacity
1452  *
1453  * @v http              HTTP request
1454  * @v block             Block data interface
1455  * @ret rc              Return status code
1456  */
1457 static int http_block_read_capacity ( struct http_request *http,
1458                                       struct interface *block ) {
1459
1460         return http_partial_read ( http, block, 0, 0, 0 );
1461 }
1462
1463 /**
1464  * Describe HTTP device in an ACPI table
1465  *
1466  * @v http              HTTP request
1467  * @v acpi              ACPI table
1468  * @v len               Length of ACPI table
1469  * @ret rc              Return status code
1470  */
1471 static int http_acpi_describe ( struct http_request *http,
1472                                 struct acpi_description_header *acpi,
1473                                 size_t len ) {
1474
1475         DBGC ( http, "HTTP %p cannot yet describe device in an ACPI table\n",
1476                http );
1477         ( void ) acpi;
1478         ( void ) len;
1479         return 0;
1480 }
1481
1482 /** HTTP socket interface operations */
1483 static struct interface_operation http_socket_operations[] = {
1484         INTF_OP ( xfer_window, struct http_request *, http_socket_window ),
1485         INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ),
1486         INTF_OP ( xfer_window_changed, struct http_request *, http_step ),
1487         INTF_OP ( intf_close, struct http_request *, http_socket_close ),
1488 };
1489
1490 /** HTTP socket interface descriptor */
1491 static struct interface_descriptor http_socket_desc =
1492         INTF_DESC_PASSTHRU ( struct http_request, socket,
1493                              http_socket_operations, xfer );
1494
1495 /** HTTP partial transfer interface operations */
1496 static struct interface_operation http_partial_operations[] = {
1497         INTF_OP ( intf_close, struct http_request *, http_close ),
1498 };
1499
1500 /** HTTP partial transfer interface descriptor */
1501 static struct interface_descriptor http_partial_desc =
1502         INTF_DESC ( struct http_request, partial, http_partial_operations );
1503
1504 /** HTTP data transfer interface operations */
1505 static struct interface_operation http_xfer_operations[] = {
1506         INTF_OP ( xfer_window, struct http_request *, http_xfer_window ),
1507         INTF_OP ( block_read, struct http_request *, http_block_read ),
1508         INTF_OP ( block_read_capacity, struct http_request *,
1509                   http_block_read_capacity ),
1510         INTF_OP ( intf_close, struct http_request *, http_close ),
1511         INTF_OP ( acpi_describe, struct http_request *, http_acpi_describe ),
1512 };
1513
1514 /** HTTP data transfer interface descriptor */
1515 static struct interface_descriptor http_xfer_desc =
1516         INTF_DESC_PASSTHRU ( struct http_request, xfer,
1517                              http_xfer_operations, socket );
1518
1519 /** HTTP process descriptor */
1520 static struct process_descriptor http_process_desc =
1521         PROC_DESC_ONCE ( struct http_request, process, http_step );
1522
1523 /**
1524  * Initiate an HTTP connection, with optional filter
1525  *
1526  * @v xfer              Data transfer interface
1527  * @v uri               Uniform Resource Identifier
1528  * @v default_port      Default port number
1529  * @v filter            Filter to apply to socket, or NULL
1530  * @ret rc              Return status code
1531  */
1532 int http_open_filter ( struct interface *xfer, struct uri *uri,
1533                        unsigned int default_port,
1534                        int ( * filter ) ( struct interface *xfer,
1535                                           const char *name,
1536                                           struct interface **next ) ) {
1537         struct http_request *http;
1538         int rc;
1539
1540         /* Sanity checks */
1541         if ( ! uri->host )
1542                 return -EINVAL;
1543
1544         /* Allocate and populate HTTP structure */
1545         http = zalloc ( sizeof ( *http ) );
1546         if ( ! http )
1547                 return -ENOMEM;
1548         ref_init ( &http->refcnt, http_free );
1549         intf_init ( &http->xfer, &http_xfer_desc, &http->refcnt );
1550         intf_init ( &http->partial, &http_partial_desc, &http->refcnt );
1551         http->uri = uri_get ( uri );
1552         http->default_port = default_port;
1553         http->filter = filter;
1554         intf_init ( &http->socket, &http_socket_desc, &http->refcnt );
1555         process_init ( &http->process, &http_process_desc, &http->refcnt );
1556         timer_init ( &http->timer, http_retry, &http->refcnt );
1557         http->flags = HTTP_TX_PENDING;
1558
1559         /* Open socket */
1560         if ( ( rc = http_socket_open ( http ) ) != 0 )
1561                 goto err;
1562
1563         /* Attach to parent interface, mortalise self, and return */
1564         intf_plug_plug ( &http->xfer, xfer );
1565         ref_put ( &http->refcnt );
1566         return 0;
1567
1568  err:
1569         DBGC ( http, "HTTP %p could not create request: %s\n",
1570                http, strerror ( rc ) );
1571         http_close ( http, rc );
1572         ref_put ( &http->refcnt );
1573         return rc;
1574 }