iPXE
httpcore.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 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 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27/**
28 * @file
29 *
30 * Hyper Text Transfer Protocol (HTTP) core functionality
31 *
32 */
33
34#include <stdint.h>
35#include <stdlib.h>
36#include <stdio.h>
37#include <string.h>
38#include <strings.h>
39#include <byteswap.h>
40#include <errno.h>
41#include <ctype.h>
42#include <assert.h>
43#include <ipxe/uri.h>
44#include <ipxe/refcnt.h>
45#include <ipxe/iobuf.h>
46#include <ipxe/xfer.h>
47#include <ipxe/open.h>
48#include <ipxe/process.h>
49#include <ipxe/retry.h>
50#include <ipxe/timer.h>
51#include <ipxe/linebuf.h>
52#include <ipxe/xferbuf.h>
53#include <ipxe/blockdev.h>
54#include <ipxe/acpi.h>
55#include <ipxe/version.h>
56#include <ipxe/params.h>
57#include <ipxe/profile.h>
58#include <ipxe/vsprintf.h>
59#include <ipxe/errortab.h>
60#include <ipxe/efi/efi_path.h>
61#include <ipxe/http.h>
62
63/* Disambiguate the various error causes */
64#define EACCES_401 __einfo_error ( EINFO_EACCES_401 )
65#define EINFO_EACCES_401 \
66 __einfo_uniqify ( EINFO_EACCES, 0x01, "HTTP 401 Unauthorized" )
67#define EINVAL_STATUS __einfo_error ( EINFO_EINVAL_STATUS )
68#define EINFO_EINVAL_STATUS \
69 __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid status line" )
70#define EINVAL_HEADER __einfo_error ( EINFO_EINVAL_HEADER )
71#define EINFO_EINVAL_HEADER \
72 __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid header" )
73#define EINVAL_CONTENT_LENGTH __einfo_error ( EINFO_EINVAL_CONTENT_LENGTH )
74#define EINFO_EINVAL_CONTENT_LENGTH \
75 __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid content length" )
76#define EINVAL_CHUNK_LENGTH __einfo_error ( EINFO_EINVAL_CHUNK_LENGTH )
77#define EINFO_EINVAL_CHUNK_LENGTH \
78 __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid chunk length" )
79#define EIO_OTHER __einfo_error ( EINFO_EIO_OTHER )
80#define EINFO_EIO_OTHER \
81 __einfo_uniqify ( EINFO_EIO, 0x01, "Unrecognised HTTP response code" )
82#define EIO_CONTENT_LENGTH __einfo_error ( EINFO_EIO_CONTENT_LENGTH )
83#define EINFO_EIO_CONTENT_LENGTH \
84 __einfo_uniqify ( EINFO_EIO, 0x02, "Content length mismatch" )
85#define EIO_4XX __einfo_error ( EINFO_EIO_4XX )
86#define EINFO_EIO_4XX \
87 __einfo_uniqify ( EINFO_EIO, 0x04, "HTTP 4xx Client Error" )
88#define EIO_5XX __einfo_error ( EINFO_EIO_5XX )
89#define EINFO_EIO_5XX \
90 __einfo_uniqify ( EINFO_EIO, 0x05, "HTTP 5xx Server Error" )
91#define ENOENT_404 __einfo_error ( EINFO_ENOENT_404 )
92#define EINFO_ENOENT_404 \
93 __einfo_uniqify ( EINFO_ENOENT, 0x01, "Not found" )
94#define ENOTSUP_CONNECTION __einfo_error ( EINFO_ENOTSUP_CONNECTION )
95#define EINFO_ENOTSUP_CONNECTION \
96 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported connection header" )
97#define ENOTSUP_TRANSFER __einfo_error ( EINFO_ENOTSUP_TRANSFER )
98#define EINFO_ENOTSUP_TRANSFER \
99 __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported transfer encoding" )
100#define EPERM_403 __einfo_error ( EINFO_EPERM_403 )
101#define EINFO_EPERM_403 \
102 __einfo_uniqify ( EINFO_EPERM, 0x01, "HTTP 403 Forbidden" )
103#define EPROTO_UNSOLICITED __einfo_error ( EINFO_EPROTO_UNSOLICITED )
104#define EINFO_EPROTO_UNSOLICITED \
105 __einfo_uniqify ( EINFO_EPROTO, 0x01, "Unsolicited data" )
106
107/** Retry delay used when we cannot understand the Retry-After header */
108#define HTTP_RETRY_SECONDS 5
109
110/** Idle connection watchdog timeout */
111#define HTTP_WATCHDOG_SECONDS 120
112
113/** Receive profiler */
114static struct profiler http_rx_profiler __profiler = { .name = "http.rx" };
115
116/** Data transfer profiler */
117static struct profiler http_xfer_profiler __profiler = { .name = "http.xfer" };
118
119/** Human-readable error messages */
125
130
131/******************************************************************************
132 *
133 * Methods
134 *
135 ******************************************************************************
136 */
137
138/** HTTP HEAD method */
139struct http_method http_head __http_method = {
140 .name = "HEAD",
141};
142
143/** HTTP GET method */
144struct http_method http_get __http_method = {
145 .name = "GET",
146};
147
148/** HTTP POST method */
149struct http_method http_post __http_method = {
150 .name = "POST",
151};
152
153/** HTTP PUT method */
154struct http_method http_put __http_method = {
155 .name = "PUT",
156};
157
158/**
159 * Identify HTTP method
160 *
161 * @v name Method name
162 * @ret method HTTP method, or NULL if not known
163 */
164static struct http_method * http_method ( const char *name ) {
165 struct http_method *method;
166
167 /* Identify method */
169 if ( strcasecmp ( name, method->name ) == 0 )
170 return method;
171 }
172
173 return NULL;
174}
175
176/******************************************************************************
177 *
178 * Utility functions
179 *
180 ******************************************************************************
181 */
182
183/**
184 * Handle received HTTP line-buffered data
185 *
186 * @v http HTTP transaction
187 * @v iobuf I/O buffer
188 * @v linebuf Line buffer
189 * @ret rc Return status code
190 */
191static int http_rx_linebuf ( struct http_transaction *http,
192 struct io_buffer *iobuf,
193 struct line_buffer *linebuf ) {
194 int consumed;
195 int rc;
196
197 /* Buffer received line */
198 consumed = line_buffer ( linebuf, iobuf->data, iob_len ( iobuf ) );
199 if ( consumed < 0 ) {
200 rc = consumed;
201 DBGC ( http, "HTTP %p could not buffer line: %s\n",
202 http, strerror ( rc ) );
203 return rc;
204 }
205
206 /* Consume line */
207 iob_pull ( iobuf, consumed );
208
209 return 0;
210}
211
212/**
213 * Get HTTP response token
214 *
215 * @v line Line position
216 * @v value Token value to fill in (if any)
217 * @ret token Token, or NULL
218 */
219char * http_token ( char **line, char **value ) {
220 char *token;
221 char quote = '\0';
222 char c;
223
224 /* Avoid returning uninitialised data */
225 if ( value )
226 *value = NULL;
227
228 /* Skip any initial whitespace or commas */
229 while ( ( isspace ( **line ) ) || ( **line == ',' ) )
230 (*line)++;
231
232 /* Check for end of line and record token position */
233 if ( ! **line )
234 return NULL;
235 token = *line;
236
237 /* Scan for end of token */
238 while ( ( c = **line ) ) {
239
240 /* Terminate if we hit an unquoted whitespace or comma */
241 if ( ( isspace ( c ) || ( c == ',' ) ) && ! quote )
242 break;
243
244 /* Terminate if we hit a closing quote */
245 if ( c == quote )
246 break;
247
248 /* Check for value separator */
249 if ( value && ( ! *value ) && ( c == '=' ) ) {
250
251 /* Terminate key portion of token */
252 *((*line)++) = '\0';
253
254 /* Check for quote character */
255 c = **line;
256 if ( ( c == '"' ) || ( c == '\'' ) ) {
257 quote = c;
258 (*line)++;
259 }
260
261 /* Record value portion of token */
262 *value = *line;
263
264 } else {
265
266 /* Move to next character */
267 (*line)++;
268 }
269 }
270
271 /* Terminate token, if applicable */
272 if ( c )
273 *((*line)++) = '\0';
274
275 return token;
276}
277
278/******************************************************************************
279 *
280 * Transactions
281 *
282 ******************************************************************************
283 */
284
285/**
286 * Free HTTP transaction
287 *
288 * @v refcnt Reference count
289 */
290static void http_free ( struct refcnt *refcnt ) {
291 struct http_transaction *http =
293
295 empty_line_buffer ( &http->linebuf );
296 uri_put ( http->uri );
297 free ( http );
298}
299
300/**
301 * Close HTTP transaction
302 *
303 * @v http HTTP transaction
304 * @v rc Reason for close
305 */
306static void http_close ( struct http_transaction *http, int rc ) {
307
308 /* Stop process */
309 process_del ( &http->process );
310
311 /* Stop timers */
312 stop_timer ( &http->retry );
313 stop_timer ( &http->watchdog );
314
315 /* Close all interfaces */
316 intfs_shutdown ( rc, &http->conn, &http->transfer, &http->content,
317 &http->xfer, NULL );
318}
319
320/**
321 * Close HTTP transaction with error (even if none specified)
322 *
323 * @v http HTTP transaction
324 * @v rc Reason for close
325 */
326static void http_close_error ( struct http_transaction *http, int rc ) {
327
328 /* Treat any close as an error */
329 http_close ( http, ( rc ? rc : -EPIPE ) );
330}
331
332/**
333 * Hold off HTTP idle connection watchdog timer
334 *
335 * @v http HTTP transaction
336 */
337static inline void http_watchdog ( struct http_transaction *http ) {
338
339 /* (Re)start watchdog timer */
342}
343
344/**
345 * Reopen stale HTTP connection
346 *
347 * @v http HTTP transaction
348 */
349static void http_reopen ( struct http_transaction *http ) {
350 int rc;
351
352 /* Close existing connection */
353 intf_restart ( &http->conn, -ECANCELED );
354
355 /* Reopen connection */
356 if ( ( rc = http_connect ( &http->conn, http->uri ) ) != 0 ) {
357 DBGC ( http, "HTTP %p could not reconnect: %s\n",
358 http, strerror ( rc ) );
359 goto err_connect;
360 }
361
362 /* Reset state */
363 http->state = &http_request;
364
365 /* Restart idle connection watchdog timer */
366 http_watchdog ( http );
367
368 /* Reschedule transmission process */
369 process_add ( &http->process );
370
371 return;
372
373 err_connect:
374 http_close ( http, rc );
375}
376
377/**
378 * Handle connection retry timer expiry
379 *
380 * @v retry Retry timer
381 * @v over Failure indicator
382 */
384 int over __unused ) {
385 struct http_transaction *http =
387
388 /* Reopen connection */
389 http_reopen ( http );
390}
391
392/**
393 * Handle idle connection watchdog timer expiry
394 *
395 * @v watchdog Idle connection watchdog timer
396 * @v over Failure indicator
397 */
399 int over __unused ) {
400 struct http_transaction *http =
402
403 /* Abort connection */
404 DBGC ( http, "HTTP %p aborting idle connection\n", http );
405 http_close ( http, -ETIMEDOUT );
406}
407
408/**
409 * HTTP transmit process
410 *
411 * @v http HTTP transaction
412 */
413static void http_step ( struct http_transaction *http ) {
414 int rc;
415
416 /* Do nothing if we have nothing to transmit */
417 if ( ! http->state->tx )
418 return;
419
420 /* Do nothing until connection is ready */
421 if ( ! xfer_window ( &http->conn ) )
422 return;
423
424 /* Notify data transfer interface that window may have changed */
425 xfer_window_changed ( &http->xfer );
426
427 /* Do nothing until data transfer interface is ready */
428 if ( ! xfer_window ( &http->xfer ) )
429 return;
430
431 /* Transmit data */
432 if ( ( rc = http->state->tx ( http ) ) != 0 )
433 goto err;
434
435 return;
436
437 err:
438 http_close ( http, rc );
439}
440
441/**
442 * Handle received HTTP data
443 *
444 * @v http HTTP transaction
445 * @v iobuf I/O buffer
446 * @v meta Transfer metadata
447 * @ret rc Return status code
448 *
449 * This function takes ownership of the I/O buffer.
450 */
451static int http_conn_deliver ( struct http_transaction *http,
452 struct io_buffer *iobuf,
453 struct xfer_metadata *meta __unused ) {
454 int rc;
455
456 /* Handle received data */
457 profile_start ( &http_rx_profiler );
458 while ( iobuf && iob_len ( iobuf ) ) {
459
460 /* Sanity check */
461 if ( ( ! http->state ) || ( ! http->state->rx ) ) {
462 DBGC ( http, "HTTP %p unexpected data\n", http );
464 goto err;
465 }
466
467 /* Receive (some) data */
468 if ( ( rc = http->state->rx ( http, &iobuf ) ) != 0 )
469 goto err;
470 }
471
472 /* Free I/O buffer, if applicable */
473 free_iob ( iobuf );
474
475 profile_stop ( &http_rx_profiler );
476 return 0;
477
478 err:
479 free_iob ( iobuf );
480 http_close ( http, rc );
481 return rc;
482}
483
484/**
485 * Handle server connection close
486 *
487 * @v http HTTP transaction
488 * @v rc Reason for close
489 */
490static void http_conn_close ( struct http_transaction *http, int rc ) {
491
492 /* Sanity checks */
493 assert ( http->state != NULL );
494 assert ( http->state->close != NULL );
495
496 /* Restart server connection interface */
497 intf_restart ( &http->conn, rc );
498
499 /* Hand off to state-specific method */
500 http->state->close ( http, rc );
501}
502
503/**
504 * Handle received content-decoded data
505 *
506 * @v http HTTP transaction
507 * @v iobuf I/O buffer
508 * @v meta Data transfer metadata
509 */
510static int http_content_deliver ( struct http_transaction *http,
511 struct io_buffer *iobuf,
512 struct xfer_metadata *meta ) {
513 int rc;
514
515 /* Ignore content if this is anything other than a successful
516 * transfer.
517 */
518 if ( http->response.rc != 0 ) {
519 free_iob ( iobuf );
520 return 0;
521 }
522
523 /* Hold off idle connection watchdog timer */
524 http_watchdog ( http );
525
526 /* Deliver to data transfer interface */
527 profile_start ( &http_xfer_profiler );
528 if ( ( rc = xfer_deliver ( &http->xfer, iob_disown ( iobuf ),
529 meta ) ) != 0 )
530 return rc;
531 profile_stop ( &http_xfer_profiler );
532
533 return 0;
534}
535
536/**
537 * Get underlying data transfer buffer
538 *
539 * @v http HTTP transaction
540 * @ret xferbuf Data transfer buffer, or NULL on error
541 */
542static struct xfer_buffer *
544
545 /* Deny access to the data transfer buffer if this is anything
546 * other than a successful transfer.
547 */
548 if ( http->response.rc != 0 )
549 return NULL;
550
551 /* Hand off to data transfer interface */
552 return xfer_buffer ( &http->xfer );
553}
554
555/**
556 * Read from block device (when HTTP block device support is not present)
557 *
558 * @v http HTTP transaction
559 * @v data Data interface
560 * @v lba Starting logical block address
561 * @v count Number of logical blocks
562 * @v buffer Data buffer
563 * @v len Length of data buffer
564 * @ret rc Return status code
565 */
567 struct interface *data __unused,
568 uint64_t lba __unused, unsigned int count __unused,
569 void *buffer __unused, size_t len __unused ) {
570
571 return -ENOTSUP;
572}
573
574/**
575 * Read block device capacity (when HTTP block device support is not present)
576 *
577 * @v control Control interface
578 * @v data Data interface
579 * @ret rc Return status code
580 */
582 struct interface *data __unused ) {
583
584 return -ENOTSUP;
585}
586
587/**
588 * Describe as an EFI device path
589 *
590 * @v http HTTP transaction
591 * @ret path EFI device path, or NULL on error
592 */
595
596 return efi_uri_path ( http->uri );
597}
598
599/** HTTP data transfer interface operations */
609
610/** HTTP data transfer interface descriptor */
613 http_xfer_operations, content );
614
615/** HTTP content-decoded interface operations */
622
623/** HTTP content-decoded interface descriptor */
625 INTF_DESC_PASSTHRU ( struct http_transaction, content,
627
628/** HTTP transfer-decoded interface operations */
632
633/** HTTP transfer-decoded interface descriptor */
635 INTF_DESC_PASSTHRU ( struct http_transaction, transfer,
637
638/** HTTP server connection interface operations */
645
646/** HTTP server connection interface descriptor */
649 http_conn_operations, transfer );
650
651/** HTTP process descriptor */
654
655/**
656 * Open HTTP transaction
657 *
658 * @v xfer Data transfer interface
659 * @v method Request method
660 * @v uri Request URI
661 * @v range Content range (if any)
662 * @v content Request content (if any)
663 * @ret rc Return status code
664 */
665int http_open ( struct interface *xfer, struct http_method *method,
666 struct uri *uri, struct http_request_range *range,
667 struct http_request_content *content ) {
668 struct http_transaction *http;
669 struct uri request_uri;
670 struct uri request_host;
671 size_t request_uri_len;
672 size_t request_host_len;
673 size_t content_len;
674 char *request_uri_string;
675 char *request_host_string;
676 void *content_data;
677 int rc;
678
679 /* Calculate request URI length */
680 memset ( &request_uri, 0, sizeof ( request_uri ) );
681 request_uri.epath = ( uri->epath ? uri->epath : "/" );
682 request_uri.equery = uri->equery;
683 request_uri_len =
684 ( format_uri ( &request_uri, NULL, 0 ) + 1 /* NUL */);
685
686 /* Calculate host name length */
687 memset ( &request_host, 0, sizeof ( request_host ) );
688 request_host.host = uri->host;
689 request_host.port = uri->port;
690 request_host_len =
691 ( format_uri ( &request_host, NULL, 0 ) + 1 /* NUL */ );
692
693 /* Calculate request content length */
694 content_len = ( content ? content->len : 0 );
695
696 /* Allocate and initialise structure */
697 http = zalloc ( sizeof ( *http ) + request_uri_len + request_host_len +
698 content_len );
699 if ( ! http ) {
700 rc = -ENOMEM;
701 goto err_alloc;
702 }
703 request_uri_string = ( ( ( void * ) http ) + sizeof ( *http ) );
704 request_host_string = ( request_uri_string + request_uri_len );
705 content_data = ( request_host_string + request_host_len );
706 format_uri ( &request_uri, request_uri_string, request_uri_len );
707 format_uri ( &request_host, request_host_string, request_host_len );
708 ref_init ( &http->refcnt, http_free );
709 intf_init ( &http->xfer, &http_xfer_desc, &http->refcnt );
710 intf_init ( &http->content, &http_content_desc, &http->refcnt );
711 intf_init ( &http->transfer, &http_transfer_desc, &http->refcnt );
712 intf_init ( &http->conn, &http_conn_desc, &http->refcnt );
713 intf_plug_plug ( &http->transfer, &http->content );
714 process_init ( &http->process, &http_process_desc, &http->refcnt );
715 timer_init ( &http->retry, http_retry_expired, &http->refcnt );
716 timer_init ( &http->watchdog, http_watchdog_expired, &http->refcnt );
717 http->uri = uri_get ( uri );
718 http->request.method = method;
719 http->request.uri = request_uri_string;
720 http->request.host = request_host_string;
721 if ( range ) {
722 memcpy ( &http->request.range, range,
723 sizeof ( http->request.range ) );
724 }
725 if ( content ) {
726 http->request.content.type = content->type;
727 http->request.content.data = content_data;
728 http->request.content.len = content_len;
729 memcpy ( content_data, content->data, content_len );
730 }
731 http->state = &http_request;
732 DBGC2 ( http, "HTTP %p %s://%s%s\n", http, http->uri->scheme,
733 http->request.host, http->request.uri );
734
735 /* Open connection */
736 if ( ( rc = http_connect ( &http->conn, uri ) ) != 0 ) {
737 DBGC ( http, "HTTP %p could not connect: %s\n",
738 http, strerror ( rc ) );
739 goto err_connect;
740 }
741
742 /* Start watchdog timer */
743 http_watchdog ( http );
744
745 /* Attach to parent interface, mortalise self, and return */
746 intf_plug_plug ( &http->xfer, xfer );
747 ref_put ( &http->refcnt );
748 return 0;
749
750 err_connect:
751 http_close ( http, rc );
752 ref_put ( &http->refcnt );
753 err_alloc:
754 return rc;
755}
756
757/**
758 * Redirect HTTP transaction
759 *
760 * @v http HTTP transaction
761 * @v location New location
762 * @ret rc Return status code
763 */
764static int http_redirect ( struct http_transaction *http,
765 const char *location ) {
766 struct uri *location_uri;
767 struct uri *resolved_uri;
768 int rc;
769
770 DBGC2 ( http, "HTTP %p redirecting to \"%s\"\n", http, location );
771
772 /* Parse location URI */
773 location_uri = parse_uri ( location );
774 if ( ! location_uri ) {
775 rc = -ENOMEM;
776 goto err_parse_uri;
777 }
778
779 /* Resolve as relative to original URI */
780 resolved_uri = resolve_uri ( http->uri, location_uri );
781 if ( ! resolved_uri ) {
782 rc = -ENOMEM;
783 goto err_resolve_uri;
784 }
785
786 /* Redirect to new URI */
787 if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI,
788 resolved_uri ) ) != 0 ) {
789 DBGC ( http, "HTTP %p could not redirect: %s\n",
790 http, strerror ( rc ) );
791 goto err_redirect;
792 }
793
794 err_redirect:
795 uri_put ( resolved_uri );
796 err_resolve_uri:
797 uri_put ( location_uri );
798 err_parse_uri:
799 return rc;
800}
801
802/**
803 * Handle successful transfer completion
804 *
805 * @v http HTTP transaction
806 * @ret rc Return status code
807 */
808static int http_transfer_complete ( struct http_transaction *http ) {
809 struct http_authentication *auth;
810 const char *location;
811 int rc;
812
813 /* Keep connection alive if applicable */
815 pool_recycle ( &http->conn );
816
817 /* Restart server connection interface */
818 intf_restart ( &http->conn, 0 );
819
820 /* No more data is expected */
821 http->state = NULL;
822
823 /* If transaction is successful, then close the
824 * transfer-decoded interface. The content encoding may
825 * choose whether or not to immediately terminate the
826 * transaction.
827 */
828 if ( http->response.rc == 0 ) {
829 intf_shutdown ( &http->transfer, 0 );
830 return 0;
831 }
832
833 /* Perform redirection, if applicable */
834 if ( ( location = http->response.location ) ) {
835 if ( ( rc = http_redirect ( http, location ) ) != 0 )
836 return rc;
837 http_close ( http, 0 );
838 return 0;
839 }
840
841 /* Fail unless a retry is permitted */
842 if ( ! ( http->response.flags & HTTP_RESPONSE_RETRY ) )
843 return http->response.rc;
844
845 /* Perform authentication, if applicable */
846 if ( ( auth = http->response.auth.auth ) ) {
847 http->request.auth.auth = auth;
848 DBGC2 ( http, "HTTP %p performing %s authentication\n",
849 http, auth->name );
850 if ( ( rc = auth->authenticate ( http ) ) != 0 ) {
851 DBGC ( http, "HTTP %p could not authenticate: %s\n",
852 http, strerror ( rc ) );
853 return rc;
854 }
855 }
856
857 /* Restart content decoding interfaces */
858 intfs_restart ( http->response.rc, &http->content, &http->transfer,
859 NULL );
860 intf_plug_plug ( &http->transfer, &http->content );
861 http->len = 0;
862 assert ( http->remaining == 0 );
863
864 /* Retry immediately if applicable. We cannot rely on an
865 * immediate timer expiry, since certain Microsoft-designed
866 * HTTP extensions such as NTLM break the fundamentally
867 * stateless nature of HTTP and rely on the same connection
868 * being reused for authentication. See RFC7230 section 2.3
869 * for further details.
870 */
871 if ( ! http->response.retry_after ) {
872 http_reopen ( http );
873 return 0;
874 }
875
876 /* Start timer to initiate retry */
877 DBGC2 ( http, "HTTP %p retrying after %d seconds\n",
878 http, http->response.retry_after );
879 start_timer_fixed ( &http->retry,
880 ( http->response.retry_after * TICKS_PER_SEC ) );
881 stop_timer ( &http->watchdog );
882 return 0;
883}
884
885/******************************************************************************
886 *
887 * Requests
888 *
889 ******************************************************************************
890 */
891
892/**
893 * Construct HTTP request headers
894 *
895 * @v http HTTP transaction
896 * @v buf Buffer
897 * @v len Length of buffer
898 * @ret len Length, or negative error
899 */
900static int http_format_headers ( struct http_transaction *http, char *buf,
901 size_t len ) {
902 struct parameters *params = http->uri->params;
904 struct parameter *param;
905 size_t used;
906 size_t remaining;
907 char *line;
908 int value_len;
909 int rc;
910
911 /* Construct request line */
912 used = ssnprintf ( buf, len, "%s %s HTTP/1.1",
913 http->request.method->name, http->request.uri );
914 if ( used < len )
915 DBGC2 ( http, "HTTP %p TX %s\n", http, buf );
916 used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" );
917
918 /* Construct all fixed headers */
920
921 /* Determine header value length */
922 value_len = header->format ( http, NULL, 0 );
923 if ( value_len < 0 ) {
924 rc = value_len;
925 return rc;
926 }
927
928 /* Skip zero-length headers */
929 if ( ! value_len )
930 continue;
931
932 /* Construct header */
933 line = ( buf + used );
934 used += ssnprintf ( ( buf + used ), ( len - used ), "%s: ",
935 header->name );
936 remaining = ( ( used < len ) ? ( len - used ) : 0 );
937 used += header->format ( http, ( buf + used ), remaining );
938 if ( used < len )
939 DBGC2 ( http, "HTTP %p TX %s\n", http, line );
940 used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" );
941 }
942
943 /* Construct parameter headers, if any */
944 if ( params ) {
945
946 /* Construct all parameter headers */
947 for_each_param ( param, params ) {
948
949 /* Skip non-header parameters */
950 if ( ! ( param->flags & PARAMETER_HEADER ) )
951 continue;
952
953 /* Add parameter */
954 used += ssnprintf ( ( buf + used ), ( len - used ),
955 "%s: %s\r\n", param->key,
956 param->value );
957 if ( used < len ) {
958 DBGC2 ( http, "HTTP %p TX %s: %s\n",
959 http, param->key, param->value );
960 }
961 }
962 }
963
964 /* Construct terminating newline */
965 used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" );
966
967 return used;
968}
969
970/**
971 * Construct HTTP "Host" header
972 *
973 * @v http HTTP transaction
974 * @v buf Buffer
975 * @v len Length of buffer
976 * @ret len Length of header value, or negative error
977 */
978static int http_format_host ( struct http_transaction *http, char *buf,
979 size_t len ) {
980
981 /* Construct host URI */
982 return snprintf ( buf, len, "%s", http->request.host );
983}
984
985/** HTTP "Host" header "*/
986struct http_request_header http_request_host __http_request_header = {
987 .name = "Host",
988 .format = http_format_host,
989};
990
991/**
992 * Construct HTTP "User-Agent" header
993 *
994 * @v http HTTP transaction
995 * @v buf Buffer
996 * @v len Length of buffer
997 * @ret len Length of header value, or negative error
998 */
1000 char *buf, size_t len ) {
1001
1002 /* Construct user agent */
1003 return snprintf ( buf, len, "iPXE/%s", product_version );
1004}
1005
1006/** HTTP "User-Agent" header */
1007struct http_request_header http_request_user_agent __http_request_header = {
1008 .name = "User-Agent",
1009 .format = http_format_user_agent,
1010};
1011
1012/**
1013 * Construct HTTP "Connection" header
1014 *
1015 * @v http HTTP transaction
1016 * @v buf Buffer
1017 * @v len Length of buffer
1018 * @ret len Length of header value, or negative error
1019 */
1021 char *buf, size_t len ) {
1022
1023 /* Always request keep-alive */
1024 return snprintf ( buf, len, "keep-alive" );
1025}
1026
1027/** HTTP "Connection" header */
1028struct http_request_header http_request_connection __http_request_header = {
1029 .name = "Connection",
1030 .format = http_format_connection,
1031};
1032
1033/**
1034 * Construct HTTP "Range" header
1035 *
1036 * @v http HTTP transaction
1037 * @v buf Buffer
1038 * @v len Length of buffer
1039 * @ret len Length of header value, or negative error
1040 */
1041static int http_format_range ( struct http_transaction *http,
1042 char *buf, size_t len ) {
1043
1044 /* Construct range, if applicable */
1045 if ( http->request.range.len ) {
1046 return snprintf ( buf, len, "bytes=%zd-%zd",
1047 http->request.range.start,
1048 ( http->request.range.start +
1049 http->request.range.len - 1 ) );
1050 } else {
1051 return 0;
1052 }
1053}
1054
1055/** HTTP "Range" header */
1057 .name = "Range",
1058 .format = http_format_range,
1059};
1060
1061/**
1062 * Construct HTTP "Content-Type" header
1063 *
1064 * @v http HTTP transaction
1065 * @v buf Buffer
1066 * @v len Length of buffer
1067 * @ret len Length of header value, or negative error
1068 */
1070 char *buf, size_t len ) {
1071
1072 /* Construct content type, if applicable */
1073 if ( http->request.content.type ) {
1074 return snprintf ( buf, len, "%s", http->request.content.type );
1075 } else {
1076 return 0;
1077 }
1078}
1079
1080/** HTTP "Content-Type" header */
1081struct http_request_header http_request_content_type __http_request_header = {
1082 .name = "Content-Type",
1083 .format = http_format_content_type,
1084};
1085
1086/**
1087 * Construct HTTP "Content-Length" header
1088 *
1089 * @v http HTTP transaction
1090 * @v buf Buffer
1091 * @v len Length of buffer
1092 * @ret len Length of header value, or negative error
1093 */
1095 char *buf, size_t len ) {
1096
1097 /* Construct content length, if applicable */
1098 if ( http->request.content.len ) {
1099 return snprintf ( buf, len, "%zd", http->request.content.len );
1100 } else {
1101 return 0;
1102 }
1103}
1104
1105/** HTTP "Content-Length" header */
1106struct http_request_header http_request_content_length __http_request_header = {
1107 .name = "Content-Length",
1109};
1110
1111/**
1112 * Construct HTTP "Accept-Encoding" header
1113 *
1114 * @v http HTTP transaction
1115 * @v buf Buffer
1116 * @v len Length of buffer
1117 * @ret len Length of header value, or negative error
1118 */
1120 char *buf, size_t len ) {
1121 struct http_content_encoding *encoding;
1122 const char *sep = "";
1123 size_t used = 0;
1124
1125 /* Construct list of content encodings */
1127 if ( encoding->supported && ( ! encoding->supported ( http ) ) )
1128 continue;
1129 used += ssnprintf ( ( buf + used ), ( len - used ),
1130 "%s%s", sep, encoding->name );
1131 sep = ", ";
1132 }
1133
1134 return used;
1135}
1136
1137/** HTTP "Accept-Encoding" header */
1138struct http_request_header http_request_accept_encoding __http_request_header ={
1139 .name = "Accept-Encoding",
1141};
1142
1143/**
1144 * Transmit request
1145 *
1146 * @v http HTTP transaction
1147 * @ret rc Return status code
1148 */
1149static int http_tx_request ( struct http_transaction *http ) {
1150 struct io_buffer *iobuf;
1151 int len;
1152 int check_len;
1153 int rc;
1154
1155 /* Calculate request length */
1156 len = http_format_headers ( http, NULL, 0 );
1157 if ( len < 0 ) {
1158 rc = len;
1159 DBGC ( http, "HTTP %p could not construct request: %s\n",
1160 http, strerror ( rc ) );
1161 goto err_len;
1162 }
1163
1164 /* Allocate I/O buffer */
1165 iobuf = xfer_alloc_iob ( &http->conn, ( len + 1 /* NUL */ +
1166 http->request.content.len ) );
1167 if ( ! iobuf ) {
1168 rc = -ENOMEM;
1169 goto err_alloc;
1170 }
1171
1172 /* Construct request */
1173 check_len = http_format_headers ( http, iob_put ( iobuf, len ),
1174 ( len + 1 /* NUL */ ) );
1175 assert ( check_len == len );
1176 memcpy ( iob_put ( iobuf, http->request.content.len ),
1177 http->request.content.data, http->request.content.len );
1178
1179 /* Deliver request */
1180 if ( ( rc = xfer_deliver_iob ( &http->conn,
1181 iob_disown ( iobuf ) ) ) != 0 ) {
1182 DBGC ( http, "HTTP %p could not deliver request: %s\n",
1183 http, strerror ( rc ) );
1184 goto err_deliver;
1185 }
1186
1187 /* Clear any previous response */
1189 memset ( &http->response, 0, sizeof ( http->response ) );
1190
1191 /* Move to response headers state */
1192 http->state = &http_headers;
1193
1194 return 0;
1195
1196 err_deliver:
1197 free_iob ( iobuf );
1198 err_alloc:
1199 err_len:
1200 return rc;
1201}
1202
1203/** HTTP request state */
1204static struct http_state http_request = {
1205 .tx = http_tx_request,
1206 .close = http_close_error,
1207};
1208
1209/******************************************************************************
1210 *
1211 * Response headers
1212 *
1213 ******************************************************************************
1214 */
1215
1216/**
1217 * Parse HTTP status line
1218 *
1219 * @v http HTTP transaction
1220 * @v line Status line
1221 * @ret rc Return status code
1222 */
1223static int http_parse_status ( struct http_transaction *http, char *line ) {
1224 char *endp;
1225 char *version;
1226 char *vernum;
1227 char *status;
1228 int response_rc;
1229
1230 DBGC2 ( http, "HTTP %p RX %s\n", http, line );
1231
1232 /* Parse HTTP version */
1233 version = http_token ( &line, NULL );
1234 if ( ( ! version ) || ( strncmp ( version, "HTTP/", 5 ) != 0 ) ) {
1235 DBGC ( http, "HTTP %p malformed version \"%s\"\n", http, line );
1236 return -EINVAL_STATUS;
1237 }
1238
1239 /* Keepalive is enabled by default for anything newer than HTTP/1.0 */
1240 vernum = ( version + 5 /* "HTTP/" (presence already checked) */ );
1241 if ( vernum[0] == '0' ) {
1242 /* HTTP/0.x : keepalive not enabled by default */
1243 } else if ( strncmp ( vernum, "1.0", 3 ) == 0 ) {
1244 /* HTTP/1.0 : keepalive not enabled by default */
1245 } else {
1246 /* HTTP/1.1 or newer: keepalive enabled by default */
1248 }
1249
1250 /* Parse status code */
1251 status = line;
1252 http->response.status = strtoul ( status, &endp, 10 );
1253 if ( *endp != ' ' ) {
1254 DBGC ( http, "HTTP %p malformed status code \"%s\"\n",
1255 http, status );
1256 return -EINVAL_STATUS;
1257 }
1258
1259 /* Convert HTTP status code to iPXE return status code */
1260 if ( status[0] == '2' ) {
1261 /* 2xx Success */
1262 response_rc = 0;
1263 } else if ( status[0] == '3' ) {
1264 /* 3xx Redirection */
1265 response_rc = -EXDEV;
1266 } else if ( http->response.status == 401 ) {
1267 /* 401 Unauthorized */
1268 response_rc = -EACCES_401;
1269 } else if ( http->response.status == 403 ) {
1270 /* 403 Forbidden */
1271 response_rc = -EPERM_403;
1272 } else if ( http->response.status == 404 ) {
1273 /* 404 Not Found */
1274 response_rc = -ENOENT_404;
1275 } else if ( status[0] == '4' ) {
1276 /* 4xx Client Error (not already specified) */
1277 response_rc = -EIO_4XX;
1278 } else if ( status[0] == '5' ) {
1279 /* 5xx Server Error */
1280 response_rc = -EIO_5XX;
1281 } else {
1282 /* Unrecognised */
1283 response_rc = -EIO_OTHER;
1284 }
1285 http->response.rc = response_rc;
1286 if ( response_rc )
1287 DBGC ( http, "HTTP %p status %s\n", http, status );
1288
1289 return 0;
1290}
1291
1292/**
1293 * Parse HTTP header
1294 *
1295 * @v http HTTP transaction
1296 * @v line Header line
1297 * @ret rc Return status code
1298 */
1299static int http_parse_header ( struct http_transaction *http, char *line ) {
1301 char *name = line;
1302 char *sep;
1303
1304 DBGC2 ( http, "HTTP %p RX %s\n", http, line );
1305
1306 /* Extract header name */
1307 sep = strchr ( line, ':' );
1308 if ( ! sep ) {
1309 DBGC ( http, "HTTP %p malformed header \"%s\"\n", http, line );
1310 return -EINVAL_HEADER;
1311 }
1312 *sep = '\0';
1313
1314 /* Extract remainder of line */
1315 line = ( sep + 1 );
1316 while ( isspace ( *line ) )
1317 line++;
1318
1319 /* Process header, if recognised */
1321 if ( strcasecmp ( name, header->name ) == 0 )
1322 return header->parse ( http, line );
1323 }
1324
1325 /* Unrecognised headers should be ignored */
1326 return 0;
1327}
1328
1329/**
1330 * Parse HTTP response headers
1331 *
1332 * @v http HTTP transaction
1333 * @ret rc Return status code
1334 */
1335static int http_parse_headers ( struct http_transaction *http ) {
1336 char *line;
1337 char *next;
1338 int rc;
1339
1340 /* Get status line */
1341 line = http->response.headers.data;
1342 assert ( line != NULL );
1343 next = ( line + strlen ( line ) + 1 /* NUL */ );
1344
1345 /* Parse status line */
1346 if ( ( rc = http_parse_status ( http, line ) ) != 0 )
1347 return rc;
1348
1349 /* Process header lines */
1350 while ( 1 ) {
1351
1352 /* Move to next line */
1353 line = next;
1354 next = ( line + strlen ( line ) + 1 /* NUL */ );
1355
1356 /* Stop on terminating blank line */
1357 if ( ! line[0] )
1358 return 0;
1359
1360 /* Process header line */
1361 if ( ( rc = http_parse_header ( http, line ) ) != 0 )
1362 return rc;
1363 }
1364}
1365
1366/**
1367 * Parse HTTP "Location" header
1368 *
1369 * @v http HTTP transaction
1370 * @v line Remaining header line
1371 * @ret rc Return status code
1372 */
1373static int http_parse_location ( struct http_transaction *http, char *line ) {
1374
1375 /* Store location */
1376 http->response.location = line;
1377 return 0;
1378}
1379
1380/** HTTP "Location" header */
1381struct http_response_header http_response_location __http_response_header = {
1382 .name = "Location",
1383 .parse = http_parse_location,
1384};
1385
1386/**
1387 * Parse HTTP "Transfer-Encoding" header
1388 *
1389 * @v http HTTP transaction
1390 * @v line Remaining header line
1391 * @ret rc Return status code
1392 */
1394 char *line ) {
1395 struct http_transfer_encoding *encoding;
1396
1397 /* Check for known transfer encodings */
1399 if ( strcasecmp ( line, encoding->name ) == 0 ) {
1400 http->response.transfer.encoding = encoding;
1401 return 0;
1402 }
1403 }
1404
1405 DBGC ( http, "HTTP %p unrecognised Transfer-Encoding \"%s\"\n",
1406 http, line );
1407 return -ENOTSUP_TRANSFER;
1408}
1409
1410/** HTTP "Transfer-Encoding" header */
1412http_response_transfer_encoding __http_response_header = {
1413 .name = "Transfer-Encoding",
1415};
1416
1417/**
1418 * Parse HTTP "Connection" header
1419 *
1420 * @v http HTTP transaction
1421 * @v line Remaining header line
1422 * @ret rc Return status code
1423 */
1424static int http_parse_connection ( struct http_transaction *http, char *line ) {
1425 char *token;
1426
1427 /* Check for known connection intentions */
1428 while ( ( token = http_token ( &line, NULL ) ) ) {
1429 if ( strcasecmp ( token, "keep-alive" ) == 0 )
1431 if ( strcasecmp ( token, "close" ) == 0 )
1433 }
1434
1435 return 0;
1436}
1437
1438/** HTTP "Connection" header */
1439struct http_response_header http_response_connection __http_response_header = {
1440 .name = "Connection",
1441 .parse = http_parse_connection,
1442};
1443
1444/**
1445 * Parse HTTP "Content-Length" header
1446 *
1447 * @v http HTTP transaction
1448 * @v line Remaining header line
1449 * @ret rc Return status code
1450 */
1452 char *line ) {
1453 char *endp;
1454
1455 /* Parse length */
1456 http->response.content.len = strtoul ( line, &endp, 10 );
1457 if ( *endp != '\0' ) {
1458 DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n",
1459 http, line );
1460 return -EINVAL_CONTENT_LENGTH;
1461 }
1462
1463 /* Record that we have a content length (since it may be zero) */
1465
1466 return 0;
1467}
1468
1469/** HTTP "Content-Length" header */
1471http_response_content_length __http_response_header = {
1472 .name = "Content-Length",
1474};
1475
1476/**
1477 * Parse HTTP "Content-Encoding" header
1478 *
1479 * @v http HTTP transaction
1480 * @v line Remaining header line
1481 * @ret rc Return status code
1482 */
1484 char *line ) {
1485 struct http_content_encoding *encoding;
1486
1487 /* Check for known content encodings */
1489 if ( encoding->supported && ( ! encoding->supported ( http ) ) )
1490 continue;
1491 if ( strcasecmp ( line, encoding->name ) == 0 ) {
1492 http->response.content.encoding = encoding;
1493 return 0;
1494 }
1495 }
1496
1497 /* Some servers (e.g. Apache) have a habit of specifying
1498 * unwarranted content encodings. For example, if Apache
1499 * detects (via /etc/httpd/conf/magic) that a file's contents
1500 * are gzip-compressed, it will set "Content-Encoding: x-gzip"
1501 * regardless of the client's Accept-Encoding header. The
1502 * only viable way to handle such servers is to treat unknown
1503 * content encodings as equivalent to "identity".
1504 */
1505 DBGC ( http, "HTTP %p unrecognised Content-Encoding \"%s\"\n",
1506 http, line );
1507 return 0;
1508}
1509
1510/** HTTP "Content-Encoding" header */
1512http_response_content_encoding __http_response_header = {
1513 .name = "Content-Encoding",
1515};
1516
1517/**
1518 * Parse HTTP "Retry-After" header
1519 *
1520 * @v http HTTP transaction
1521 * @v line Remaining header line
1522 * @ret rc Return status code
1523 */
1525 char *line ) {
1526 char *endp;
1527
1528 /* Try to parse value as a simple number of seconds */
1529 http->response.retry_after = strtoul ( line, &endp, 10 );
1530 if ( *endp != '\0' ) {
1531 /* For any value which is not a simple number of
1532 * seconds (e.g. a full HTTP date), just retry after a
1533 * fixed delay, since we don't have code able to parse
1534 * full HTTP dates.
1535 */
1537 DBGC ( http, "HTTP %p cannot understand Retry-After \"%s\"; "
1538 "using %d seconds\n", http, line, HTTP_RETRY_SECONDS );
1539 }
1540
1541 /* Allow HTTP request to be retried after specified delay */
1543
1544 return 0;
1545}
1546
1547/** HTTP "Retry-After" header */
1548struct http_response_header http_response_retry_after __http_response_header = {
1549 .name = "Retry-After",
1550 .parse = http_parse_retry_after,
1551};
1552
1553/**
1554 * Handle received HTTP headers
1555 *
1556 * @v http HTTP transaction
1557 * @v iobuf I/O buffer (may be claimed)
1558 * @ret rc Return status code
1559 */
1560static int http_rx_headers ( struct http_transaction *http,
1561 struct io_buffer **iobuf ) {
1562 struct http_transfer_encoding *transfer;
1563 struct http_content_encoding *content;
1564 char *line;
1565 int rc;
1566
1567 /* Buffer header line */
1568 if ( ( rc = http_rx_linebuf ( http, *iobuf,
1569 &http->response.headers ) ) != 0 )
1570 return rc;
1571
1572 /* Wait until we see the empty line marking end of headers */
1573 line = buffered_line ( &http->response.headers );
1574 if ( ( line == NULL ) || ( line[0] != '\0' ) )
1575 return 0;
1576
1577 /* Process headers */
1578 if ( ( rc = http_parse_headers ( http ) ) != 0 )
1579 return rc;
1580
1581 /* Initialise content encoding, if applicable */
1582 if ( ( content = http->response.content.encoding ) &&
1583 ( ( rc = content->init ( http ) ) != 0 ) ) {
1584 DBGC ( http, "HTTP %p could not initialise %s content "
1585 "encoding: %s\n", http, content->name, strerror ( rc ) );
1586 return rc;
1587 }
1588
1589 /* Presize receive buffer, if we have a content length */
1590 if ( http->response.content.len ) {
1591 xfer_seek ( &http->transfer, http->response.content.len );
1592 xfer_seek ( &http->transfer, 0 );
1593 }
1594
1595 /* Complete transfer if this is a HEAD request */
1596 if ( http->request.method == &http_head ) {
1597 if ( ( rc = http_transfer_complete ( http ) ) != 0 )
1598 return rc;
1599 return 0;
1600 }
1601
1602 /* Default to identity transfer encoding, if none specified */
1603 if ( ! http->response.transfer.encoding )
1605
1606 /* Move to transfer encoding-specific data state */
1607 transfer = http->response.transfer.encoding;
1608 http->state = &transfer->state;
1609
1610 /* Initialise transfer encoding */
1611 if ( ( rc = transfer->init ( http ) ) != 0 ) {
1612 DBGC ( http, "HTTP %p could not initialise %s transfer "
1613 "encoding: %s\n", http, transfer->name, strerror ( rc ));
1614 return rc;
1615 }
1616
1617 return 0;
1618}
1619
1620/** HTTP response headers state */
1621static struct http_state http_headers = {
1622 .rx = http_rx_headers,
1623 .close = http_close_error,
1624};
1625
1626/******************************************************************************
1627 *
1628 * Identity transfer encoding
1629 *
1630 ******************************************************************************
1631 */
1632
1633/**
1634 * Initialise transfer encoding
1635 *
1636 * @v http HTTP transaction
1637 * @ret rc Return status code
1638 */
1640 int rc;
1641
1642 /* Complete transfer immediately if we have a zero content length */
1643 if ( ( http->response.flags & HTTP_RESPONSE_CONTENT_LEN ) &&
1644 ( http->response.content.len == 0 ) &&
1645 ( ( rc = http_transfer_complete ( http ) ) != 0 ) )
1646 return rc;
1647
1648 return 0;
1649}
1650
1651/**
1652 * Handle received data
1653 *
1654 * @v http HTTP transaction
1655 * @v iobuf I/O buffer (may be claimed)
1656 * @ret rc Return status code
1657 */
1659 struct io_buffer **iobuf ) {
1660 size_t len = iob_len ( *iobuf );
1661 int rc;
1662
1663 /* Update lengths */
1664 http->len += len;
1665
1666 /* Fail if this transfer would overrun the expected content
1667 * length (if any).
1668 */
1669 if ( ( http->response.flags & HTTP_RESPONSE_CONTENT_LEN ) &&
1670 ( http->len > http->response.content.len ) ) {
1671 DBGC ( http, "HTTP %p content length overrun\n", http );
1672 return -EIO_CONTENT_LENGTH;
1673 }
1674
1675 /* Hand off to content encoding */
1676 if ( ( rc = xfer_deliver_iob ( &http->transfer,
1677 iob_disown ( *iobuf ) ) ) != 0 )
1678 return rc;
1679
1680 /* Complete transfer if we have received the expected content
1681 * length (if any).
1682 */
1683 if ( ( http->response.flags & HTTP_RESPONSE_CONTENT_LEN ) &&
1684 ( http->len == http->response.content.len ) &&
1685 ( ( rc = http_transfer_complete ( http ) ) != 0 ) )
1686 return rc;
1687
1688 return 0;
1689}
1690
1691/**
1692 * Handle server connection close
1693 *
1694 * @v http HTTP transaction
1695 * @v rc Reason for close
1696 */
1698 int rc ) {
1699
1700 /* Fail if any error occurred */
1701 if ( rc != 0 )
1702 goto err;
1703
1704 /* Fail if we have a content length (since we would have
1705 * already closed the connection if we had received the
1706 * correct content length).
1707 */
1709 DBGC ( http, "HTTP %p content length underrun\n", http );
1711 goto err;
1712 }
1713
1714 /* Indicate that transfer is complete */
1715 if ( ( rc = http_transfer_complete ( http ) ) != 0 )
1716 goto err;
1717
1718 return;
1719
1720 err:
1721 http_close ( http, rc );
1722}
1723
1724/** Identity transfer encoding */
1726 .name = "identity",
1728 .state = {
1731 },
1732};
1733
1734/******************************************************************************
1735 *
1736 * Chunked transfer encoding
1737 *
1738 ******************************************************************************
1739 */
1740
1741/**
1742 * Initialise transfer encoding
1743 *
1744 * @v http HTTP transaction
1745 * @ret rc Return status code
1746 */
1748
1749 /* Sanity checks */
1750 assert ( http->remaining == 0 );
1751 assert ( http->linebuf.len == 0 );
1752
1753 return 0;
1754}
1755
1756/**
1757 * Handle received chunk length
1758 *
1759 * @v http HTTP transaction
1760 * @v iobuf I/O buffer (may be claimed)
1761 * @ret rc Return status code
1762 */
1763static int http_rx_chunk_len ( struct http_transaction *http,
1764 struct io_buffer **iobuf ) {
1765 char *line;
1766 char *endp;
1767 size_t len;
1768 int rc;
1769
1770 /* Receive into temporary line buffer */
1771 if ( ( rc = http_rx_linebuf ( http, *iobuf, &http->linebuf ) ) != 0 )
1772 return rc;
1773
1774 /* Wait until we receive a non-empty line */
1775 line = buffered_line ( &http->linebuf );
1776 if ( ( line == NULL ) || ( line[0] == '\0' ) )
1777 return 0;
1778
1779 /* Parse chunk length */
1780 http->remaining = strtoul ( line, &endp, 16 );
1781 if ( *endp != '\0' ) {
1782 DBGC ( http, "HTTP %p invalid chunk length \"%s\"\n",
1783 http, line );
1784 return -EINVAL_CHUNK_LENGTH;
1785 }
1786
1787 /* Empty line buffer */
1788 empty_line_buffer ( &http->linebuf );
1789
1790 /* Update expected length */
1791 len = ( http->len + http->remaining );
1792 xfer_seek ( &http->transfer, len );
1793 xfer_seek ( &http->transfer, http->len );
1794
1795 /* If chunk length is zero, then move to response trailers state */
1796 if ( ! http->remaining )
1797 http->state = &http_trailers;
1798
1799 return 0;
1800}
1801
1802/**
1803 * Handle received chunk data
1804 *
1805 * @v http HTTP transaction
1806 * @v iobuf I/O buffer (may be claimed)
1807 * @ret rc Return status code
1808 */
1809static int http_rx_chunk_data ( struct http_transaction *http,
1810 struct io_buffer **iobuf ) {
1811 struct {
1812 uint8_t cr;
1813 uint8_t lf;
1814 } __attribute__ (( packed )) *crlf;
1815 struct io_buffer *payload;
1816 size_t len;
1817 int rc;
1818
1819 /* In the common case of a final chunk in a packet which also
1820 * includes the terminating CRLF, strip the terminating CRLF
1821 * (which we would ignore anyway) and hence avoid
1822 * unnecessarily copying the data.
1823 */
1824 len = iob_len ( *iobuf );
1825 if ( ( len >= sizeof ( *crlf ) ) &&
1826 ( ( len - sizeof ( *crlf ) ) == http->remaining ) ) {
1827 crlf = ( (*iobuf)->data + http->remaining );
1828 if ( ( crlf->cr == '\r' ) && ( crlf->lf == '\n' ) ) {
1829 iob_unput ( *iobuf, sizeof ( *crlf ) );
1830 len -= sizeof ( *crlf );
1831 }
1832 }
1833 assert ( len == iob_len ( *iobuf ) );
1834
1835 /* Use whole/partial buffer as applicable */
1836 if ( len <= http->remaining ) {
1837
1838 /* Whole buffer is to be consumed: decrease remaining
1839 * length and use original I/O buffer as payload.
1840 */
1841 payload = iob_disown ( *iobuf );
1842 http->len += len;
1843 http->remaining -= len;
1844
1845 } else {
1846
1847 /* Partial buffer is to be consumed: copy data to a
1848 * temporary I/O buffer.
1849 */
1850 payload = alloc_iob ( http->remaining );
1851 if ( ! payload ) {
1852 rc = -ENOMEM;
1853 goto err;
1854 }
1855 memcpy ( iob_put ( payload, http->remaining ), (*iobuf)->data,
1856 http->remaining );
1857 iob_pull ( *iobuf, http->remaining );
1858 http->len += http->remaining;
1859 http->remaining = 0;
1860 }
1861
1862 /* Hand off to content encoding */
1863 if ( ( rc = xfer_deliver_iob ( &http->transfer,
1864 iob_disown ( payload ) ) ) != 0 )
1865 goto err;
1866
1867 return 0;
1868
1869 err:
1870 assert ( payload == NULL );
1871 return rc;
1872}
1873
1874/**
1875 * Handle received chunked data
1876 *
1877 * @v http HTTP transaction
1878 * @v iobuf I/O buffer (may be claimed)
1879 * @ret rc Return status code
1880 */
1882 struct io_buffer **iobuf ) {
1883
1884 /* Handle as chunk length or chunk data as appropriate */
1885 if ( http->remaining ) {
1886 return http_rx_chunk_data ( http, iobuf );
1887 } else {
1888 return http_rx_chunk_len ( http, iobuf );
1889 }
1890}
1891
1892/** Chunked transfer encoding */
1893struct http_transfer_encoding http_transfer_chunked __http_transfer_encoding = {
1894 .name = "chunked",
1896 .state = {
1898 .close = http_close_error,
1899 },
1900};
1901
1902/******************************************************************************
1903 *
1904 * Response trailers
1905 *
1906 ******************************************************************************
1907 */
1908
1909/**
1910 * Handle received HTTP trailer
1911 *
1912 * @v http HTTP transaction
1913 * @v iobuf I/O buffer (may be claimed)
1914 * @ret rc Return status code
1915 */
1916static int http_rx_trailers ( struct http_transaction *http,
1917 struct io_buffer **iobuf ) {
1918 char *line;
1919 int rc;
1920
1921 /* Buffer trailer line */
1922 if ( ( rc = http_rx_linebuf ( http, *iobuf, &http->linebuf ) ) != 0 )
1923 return rc;
1924
1925 /* Wait until we see the empty line marking end of trailers */
1926 line = buffered_line ( &http->linebuf );
1927 if ( ( line == NULL ) || ( line[0] != '\0' ) )
1928 return 0;
1929
1930 /* Empty line buffer */
1931 empty_line_buffer ( &http->linebuf );
1932
1933 /* Transfer is complete */
1934 if ( ( rc = http_transfer_complete ( http ) ) != 0 )
1935 return rc;
1936
1937 return 0;
1938}
1939
1940/** HTTP response trailers state */
1941static struct http_state http_trailers = {
1942 .rx = http_rx_trailers,
1943 .close = http_close_error,
1944};
1945
1946/******************************************************************************
1947 *
1948 * Simple URI openers
1949 *
1950 ******************************************************************************
1951 */
1952
1953/**
1954 * Construct HTTP form parameter list
1955 *
1956 * @v params Parameter list
1957 * @v buf Buffer to contain HTTP POST parameters
1958 * @v len Length of buffer
1959 * @ret len Length of parameter list (excluding terminating NUL)
1960 */
1961static size_t http_form_params ( struct parameters *params, char *buf,
1962 size_t len ) {
1963 struct parameter *param;
1964 ssize_t remaining = len;
1965 size_t frag_len;
1966
1967 /* Add each parameter in the form "key=value", joined with "&" */
1968 len = 0;
1969 for_each_param ( param, params ) {
1970
1971 /* Skip non-form parameters */
1972 if ( ! ( param->flags & PARAMETER_FORM ) )
1973 continue;
1974
1975 /* Add the "&", if applicable */
1976 if ( len ) {
1977 if ( remaining > 0 )
1978 *buf = '&';
1979 buf++;
1980 len++;
1981 remaining--;
1982 }
1983
1984 /* URI-encode the key */
1985 frag_len = uri_encode_string ( 0, param->key, buf, remaining );
1986 buf += frag_len;
1987 len += frag_len;
1988 remaining -= frag_len;
1989
1990 /* Add the "=" */
1991 if ( remaining > 0 )
1992 *buf = '=';
1993 buf++;
1994 len++;
1995 remaining--;
1996
1997 /* URI-encode the value */
1998 frag_len = uri_encode_string ( 0, param->value, buf, remaining);
1999 buf += frag_len;
2000 len += frag_len;
2001 remaining -= frag_len;
2002 }
2003
2004 /* Ensure string is NUL-terminated even if no parameters are present */
2005 if ( remaining > 0 )
2006 *buf = '\0';
2007
2008 return len;
2009}
2010
2011/**
2012 * Open HTTP transaction for simple URI
2013 *
2014 * @v xfer Data transfer interface
2015 * @v uri Request URI
2016 * @ret rc Return status code
2017 */
2018int http_open_uri ( struct interface *xfer, struct uri *uri ) {
2019 struct parameters *params = uri->params;
2020 struct http_request_content content;
2021 struct http_method *method;
2022 const char *type;
2023 void *data;
2024 size_t len;
2025 size_t check_len;
2026 int rc;
2027
2028 /* Calculate length of form parameter list, if any */
2029 len = ( params ? http_form_params ( params, NULL, 0 ) : 0 );
2030
2031 /* Use POST if and only if there are form parameters */
2032 if ( len ) {
2033
2034 /* Use POST */
2035 method = &http_post;
2036 type = "application/x-www-form-urlencoded";
2037
2038 /* Allocate temporary form parameter list */
2039 data = zalloc ( len + 1 /* NUL */ );
2040 if ( ! data ) {
2041 rc = -ENOMEM;
2042 goto err_alloc;
2043 }
2044
2045 /* Construct temporary form parameter list */
2046 check_len = http_form_params ( params, data,
2047 ( len + 1 /* NUL */ ) );
2048 assert ( check_len == len );
2049
2050 } else {
2051
2052 /* Use GET */
2053 method = &http_get;
2054 type = NULL;
2055 data = NULL;
2056 }
2057
2058 /* Use explicitly requested method name if applicable */
2059 if ( params && params->method ) {
2060 method = http_method ( params->method );
2061 if ( ! method ) {
2062 DBGC ( uri, "HTTP unsupported method \"%s\"\n",
2063 params->method );
2064 rc = -ENOTSUP;
2065 goto err_method;
2066 }
2067 }
2068
2069 /* Construct request content */
2070 content.type = type;
2071 content.data = data;
2072 content.len = len;
2073
2074 /* Open HTTP transaction */
2075 if ( ( rc = http_open ( xfer, method, uri, NULL, &content ) ) != 0 )
2076 goto err_open;
2077
2078 err_open:
2079 err_method:
2080 free ( data );
2081 err_alloc:
2082 return rc;
2083}
2084
2085/* Drag in HTTP extensions */
2087REQUIRE_OBJECT ( config_http );
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
u8 token
Definition CIB_PRM.h:14
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned long long uint64_t
Definition stdint.h:13
unsigned char uint8_t
Definition stdint.h:10
signed long ssize_t
Definition stdint.h:7
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
u32 version
Driver version.
Definition ath9k_hw.c:1985
const char * name
Definition ath9k_hw.c:1986
int block_read_capacity(struct interface *control, struct interface *data)
Read block device capacity.
Definition blockdev.c:106
int block_read(struct interface *control, struct interface *data, uint64_t lba, unsigned int count, void *buffer, size_t len)
Read from block device.
Definition blockdev.c:48
Block devices.
int isspace(int character)
Check to see if character is a space.
Definition ctype.c:42
Character types.
uint32_t next
Next descriptor address.
Definition dwmac.h:11
ring len
Length.
Definition dwmac.h:226
EFI_DEVICE_PATH_PROTOCOL * efi_describe(struct interface *intf)
Describe object as an EFI device path.
Definition efi_path.c:945
EFI_DEVICE_PATH_PROTOCOL * efi_uri_path(struct uri *uri)
Construct EFI device path for URI.
Definition efi_path.c:494
EFI device paths.
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
struct ena_llq_option header
Header locations.
Definition ena.h:5
uint8_t status
Status.
Definition ena.h:5
uint8_t meta
Metadata flags.
Definition ena.h:3
Error codes.
Error message tables.
#define __errortab
Definition errortab.h:22
#define __einfo_errortab(einfo)
Definition errortab.h:24
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC2(...)
Definition compiler.h:547
#define DBGC(...)
Definition compiler.h:530
uint64_t lba
Starting block number.
Definition int13.h:11
static unsigned int count
Number of entries.
Definition dwmac.h:220
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER).
Definition netvsc.h:5
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define REQUIRE_OBJECT(object)
Require an object.
Definition compiler.h:227
#define EXDEV
Improper link.
Definition errno.h:685
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define EPIPE
Broken pipe.
Definition errno.h:620
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ECANCELED
Operation canceled.
Definition errno.h:344
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
#define REQUIRING_SYMBOL(symbol)
Specify the file's requiring symbol.
Definition compiler.h:140
Hyper Text Transport Protocol.
#define __http_transfer_encoding
Declare an HTTP transfer encoding.
Definition http.h:484
#define HTTP_CONTENT_ENCODINGS
HTTP content encoding table.
Definition http.h:512
#define HTTP_REQUEST_HEADERS
HTTP request header table.
Definition http.h:249
@ HTTP_RESPONSE_CONTENT_LEN
Content length specified.
Definition http.h:366
@ HTTP_RESPONSE_KEEPALIVE
Keep connection alive after close.
Definition http.h:364
@ HTTP_RESPONSE_RETRY
Transaction may be retried on failure.
Definition http.h:368
#define HTTP_TRANSFER_ENCODINGS
HTTP transfer encoding table.
Definition http.h:480
#define __http_response_header
Declare an HTTP response header.
Definition http.h:389
#define __http_request_header
Declare an HTTP request header.
Definition http.h:253
#define HTTP_RESPONSE_HEADERS
HTTP response header table.
Definition http.h:385
#define __http_method
Declare an HTTP method.
Definition http.h:109
#define HTTP_METHODS
HTTP method table.
Definition http.h:106
int http_block_read_capacity(struct http_transaction *http, struct interface *data)
Read block device capacity.
Definition httpblock.c:95
int http_block_read(struct http_transaction *http, struct interface *data, uint64_t lba, unsigned int count, void *buffer, size_t len)
Read from block device.
Definition httpblock.c:55
static void http_conn_close(struct http_connection *conn, int rc)
Close HTTP connection.
Definition httpconn.c:95
int http_connect(struct interface *xfer, struct uri *uri)
Connect to an HTTP server.
Definition httpconn.c:237
static void http_conn_close(struct http_transaction *http, int rc)
Handle server connection close.
Definition httpcore.c:490
#define EIO_4XX
Definition httpcore.c:85
#define EINVAL_HEADER
Definition httpcore.c:70
static int http_rx_headers(struct http_transaction *http, struct io_buffer **iobuf)
Handle received HTTP headers.
Definition httpcore.c:1560
#define EACCES_401
Definition httpcore.c:64
static int http_parse_status(struct http_transaction *http, char *line)
Parse HTTP status line.
Definition httpcore.c:1223
static int http_rx_chunk_len(struct http_transaction *http, struct io_buffer **iobuf)
Handle received chunk length.
Definition httpcore.c:1763
char * http_token(char **line, char **value)
Get HTTP response token.
Definition httpcore.c:219
static struct interface_operation http_xfer_operations[]
HTTP data transfer interface operations.
Definition httpcore.c:600
static int http_parse_header(struct http_transaction *http, char *line)
Parse HTTP header.
Definition httpcore.c:1299
#define EINVAL_STATUS
Definition httpcore.c:67
static void http_reopen(struct http_transaction *http)
Reopen stale HTTP connection.
Definition httpcore.c:349
static int http_parse_content_length(struct http_transaction *http, char *line)
Parse HTTP "Content-Length" header.
Definition httpcore.c:1451
static int http_format_range(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Range" header.
Definition httpcore.c:1041
__weak int http_block_read(struct http_transaction *http __unused, struct interface *data __unused, uint64_t lba __unused, unsigned int count __unused, void *buffer __unused, size_t len __unused)
Read from block device (when HTTP block device support is not present).
Definition httpcore.c:566
static int http_rx_trailers(struct http_transaction *http, struct io_buffer **iobuf)
Handle received HTTP trailer.
Definition httpcore.c:1916
static int http_rx_chunk_data(struct http_transaction *http, struct io_buffer **iobuf)
Handle received chunk data.
Definition httpcore.c:1809
#define ENOENT_404
Definition httpcore.c:91
static int http_format_headers(struct http_transaction *http, char *buf, size_t len)
Construct HTTP request headers.
Definition httpcore.c:900
#define EINVAL_CHUNK_LENGTH
Definition httpcore.c:76
static int http_parse_transfer_encoding(struct http_transaction *http, char *line)
Parse HTTP "Transfer-Encoding" header.
Definition httpcore.c:1393
static struct interface_descriptor http_xfer_desc
HTTP data transfer interface descriptor.
Definition httpcore.c:611
static void http_close_error(struct http_transaction *http, int rc)
Close HTTP transaction with error (even if none specified).
Definition httpcore.c:326
static int http_tx_request(struct http_transaction *http)
Transmit request.
Definition httpcore.c:1149
static int http_parse_retry_after(struct http_transaction *http, char *line)
Parse HTTP "Retry-After" header.
Definition httpcore.c:1524
static struct http_state http_trailers
HTTP response trailers state.
Definition httpcore.c:128
static struct interface_operation http_transfer_operations[]
HTTP transfer-decoded interface operations.
Definition httpcore.c:629
#define HTTP_RETRY_SECONDS
Retry delay used when we cannot understand the Retry-After header.
Definition httpcore.c:108
#define EPERM_403
Definition httpcore.c:100
static struct process_descriptor http_process_desc
HTTP process descriptor.
Definition httpcore.c:652
static void http_watchdog_expired(struct retry_timer *watchdog, int over __unused)
Handle idle connection watchdog timer expiry.
Definition httpcore.c:398
static void http_free(struct refcnt *refcnt)
Free HTTP transaction.
Definition httpcore.c:290
static int http_format_user_agent(struct http_transaction *http __unused, char *buf, size_t len)
Construct HTTP "User-Agent" header.
Definition httpcore.c:999
#define ENOTSUP_TRANSFER
Definition httpcore.c:97
static int http_rx_transfer_chunked(struct http_transaction *http, struct io_buffer **iobuf)
Handle received chunked data.
Definition httpcore.c:1881
#define EINFO_ENOENT_404
Definition httpcore.c:92
static struct interface_descriptor http_conn_desc
HTTP server connection interface descriptor.
Definition httpcore.c:647
#define EINFO_EIO_4XX
Definition httpcore.c:86
static void http_step(struct http_transaction *http)
HTTP transmit process.
Definition httpcore.c:413
static int http_rx_transfer_identity(struct http_transaction *http, struct io_buffer **iobuf)
Handle received data.
Definition httpcore.c:1658
#define EINVAL_CONTENT_LENGTH
Definition httpcore.c:73
static struct interface_operation http_content_operations[]
HTTP content-decoded interface operations.
Definition httpcore.c:616
static struct interface_descriptor http_content_desc
HTTP content-decoded interface descriptor.
Definition httpcore.c:624
static int http_parse_headers(struct http_transaction *http)
Parse HTTP response headers.
Definition httpcore.c:1335
static void http_close_transfer_identity(struct http_transaction *http, int rc)
Handle server connection close.
Definition httpcore.c:1697
__weak int http_block_read_capacity(struct http_transaction *http __unused, struct interface *data __unused)
Read block device capacity (when HTTP block device support is not present).
Definition httpcore.c:581
static size_t http_form_params(struct parameters *params, char *buf, size_t len)
Construct HTTP form parameter list.
Definition httpcore.c:1961
static int http_redirect(struct http_transaction *http, const char *location)
Redirect HTTP transaction.
Definition httpcore.c:764
static int http_content_deliver(struct http_transaction *http, struct io_buffer *iobuf, struct xfer_metadata *meta)
Handle received content-decoded data.
Definition httpcore.c:510
#define EIO_CONTENT_LENGTH
Definition httpcore.c:82
static int http_transfer_complete(struct http_transaction *http)
Handle successful transfer completion.
Definition httpcore.c:808
int http_open(struct interface *xfer, struct http_method *method, struct uri *uri, struct http_request_range *range, struct http_request_content *content)
Open HTTP transaction.
Definition httpcore.c:665
static struct http_method * http_method(const char *name)
Identify HTTP method.
Definition httpcore.c:164
static int http_conn_deliver(struct http_transaction *http, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Handle received HTTP data.
Definition httpcore.c:451
static int http_format_accept_encoding(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Accept-Encoding" header.
Definition httpcore.c:1119
static struct xfer_buffer * http_content_buffer(struct http_transaction *http)
Get underlying data transfer buffer.
Definition httpcore.c:543
#define EINFO_EIO_5XX
Definition httpcore.c:89
static int http_parse_content_encoding(struct http_transaction *http, char *line)
Parse HTTP "Content-Encoding" header.
Definition httpcore.c:1483
static int http_format_connection(struct http_transaction *http __unused, char *buf, size_t len)
Construct HTTP "Connection" header.
Definition httpcore.c:1020
static int http_format_content_type(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Content-Type" header.
Definition httpcore.c:1069
static int http_init_transfer_chunked(struct http_transaction *http)
Initialise transfer encoding.
Definition httpcore.c:1747
#define EIO_OTHER
Definition httpcore.c:79
static struct http_transfer_encoding http_transfer_identity
Identity transfer encoding.
Definition httpcore.c:129
static int http_init_transfer_identity(struct http_transaction *http)
Initialise transfer encoding.
Definition httpcore.c:1639
static int http_parse_connection(struct http_transaction *http, char *line)
Parse HTTP "Connection" header.
Definition httpcore.c:1424
static int http_rx_linebuf(struct http_transaction *http, struct io_buffer *iobuf, struct line_buffer *linebuf)
Handle received HTTP line-buffered data.
Definition httpcore.c:191
static int http_format_content_length(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Content-Length" header.
Definition httpcore.c:1094
static void http_close(struct http_transaction *http, int rc)
Close HTTP transaction.
Definition httpcore.c:306
static struct http_state http_headers
HTTP response headers state.
Definition httpcore.c:127
static EFI_DEVICE_PATH_PROTOCOL * http_efi_describe(struct http_transaction *http)
Describe as an EFI device path.
Definition httpcore.c:594
static void http_watchdog(struct http_transaction *http)
Hold off HTTP idle connection watchdog timer.
Definition httpcore.c:337
int http_open_uri(struct interface *xfer, struct uri *uri)
Open HTTP transaction for simple URI.
Definition httpcore.c:2018
static struct interface_operation http_conn_operations[]
HTTP server connection interface operations.
Definition httpcore.c:639
#define EPROTO_UNSOLICITED
Definition httpcore.c:103
static void http_retry_expired(struct retry_timer *retry, int over __unused)
Handle connection retry timer expiry.
Definition httpcore.c:383
static int http_parse_location(struct http_transaction *http, char *line)
Parse HTTP "Location" header.
Definition httpcore.c:1373
static struct interface_descriptor http_transfer_desc
HTTP transfer-decoded interface descriptor.
Definition httpcore.c:634
#define HTTP_WATCHDOG_SECONDS
Idle connection watchdog timeout.
Definition httpcore.c:111
static int http_format_host(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Host" header.
Definition httpcore.c:978
#define EIO_5XX
Definition httpcore.c:88
uint8_t method
Definition ib_mad.h:3
#define __weak
Declare a function as weak (use before the definition).
Definition compiler.h:244
#define __attribute__(x)
Definition compiler.h:10
ACPI data structures.
#define EFI_INTF_OP
Definition efi.h:381
struct hv_monitor_parameter param[4][32]
Parameters.
Definition hyperv.h:13
Profiling.
#define __profiler
Declare a profiler.
Definition profile.h:61
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition profile.h:174
static void profile_start(struct profiler *profiler)
Start profiling.
Definition profile.h:161
iPXE timers
#define TICKS_PER_SEC
Number of ticks per second.
Definition timer.h:16
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
String functions.
void intfs_restart(int rc,...)
Shut down and restart multiple object interfaces.
Definition interface.c:387
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intfs_shutdown(int rc,...)
Shut down multiple object interfaces.
Definition interface.c:327
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition interface.c:108
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
#define INTF_DESC_PASSTHRU(object_type, intf, operations, passthru)
Define an object interface descriptor with pass-through interface.
Definition interface.h:98
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
I/O buffers.
#define iob_put(iobuf, len)
Definition iobuf.h:125
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:217
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define iob_pull(iobuf, len)
Definition iobuf.h:107
#define iob_unput(iobuf, len)
Definition iobuf.h:140
Request parameters.
#define for_each_param(param, params)
Iterate over all request parameters in a list.
Definition params.h:86
#define PARAMETER_HEADER
Request parameter is a header parameter.
Definition params.h:46
#define PARAMETER_FORM
Request parameter is a form parameter.
Definition params.h:43
Version number.
int line_buffer(struct line_buffer *linebuf, const char *data, size_t len)
Buffer up received data by lines.
Definition linebuf.c:92
char * buffered_line(struct line_buffer *linebuf)
Retrieve buffered-up line.
Definition linebuf.c:46
void empty_line_buffer(struct line_buffer *linebuf)
Discard line buffer contents.
Definition linebuf.c:66
Line buffering.
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
Data transfer interface opening.
@ LOCATION_URI
Location is a URI.
Definition open.h:28
struct pci_range range
PCI bus:dev.fn address range.
Definition pcicloud.c:40
void pool_recycle(struct interface *intf)
Recycle this connection after closing.
Definition pool.c:42
void pool_reopen(struct interface *intf)
Reopen a defunct connection.
Definition pool.c:52
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
void process_add(struct process *process)
Add process to process list.
Definition process.c:60
Processes.
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition process.h:98
static void process_init(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process and add to process list.
Definition process.h:162
Reference counting.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118
Retry timers.
@ cr
Definition sis900.h:22
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition string.c:516
char * strchr(const char *src, int character)
Find character within a string.
Definition string.c:288
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition string.c:187
int strcasecmp(const char *first, const char *second)
Compare case-insensitive strings.
Definition string.c:209
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition DevicePath.h:45
An HTTP authentication scheme.
Definition http.h:526
int(* authenticate)(struct http_transaction *http)
Perform authentication.
Definition http.h:541
const char * name
Name (e.g.
Definition http.h:528
An HTTP content encoding.
Definition http.h:494
int(* supported)(struct http_transaction *http)
Check if content encoding is supported for this request.
Definition http.h:502
int(* init)(struct http_transaction *http)
Initialise content encoding.
Definition http.h:508
const char * name
Name.
Definition http.h:496
An HTTP method.
Definition http.h:100
const char * name
Method name (e.g.
Definition http.h:102
struct http_authentication * auth
Authentication scheme (if any).
Definition http.h:197
HTTP request content descriptor.
Definition http.h:151
size_t len
Content length.
Definition http.h:157
const void * data
Content data (if any).
Definition http.h:155
const char * type
Content type (if any).
Definition http.h:153
An HTTP request header.
Definition http.h:234
HTTP request range descriptor.
Definition http.h:143
size_t start
Range start.
Definition http.h:145
size_t len
Range length, or zero for no range request.
Definition http.h:147
An HTTP request.
Definition http.h:218
struct http_request_range range
Range descriptor.
Definition http.h:226
const char * host
Server host name.
Definition http.h:224
struct http_request_auth auth
Authentication descriptor.
Definition http.h:230
struct http_method * method
Method.
Definition http.h:220
const char * uri
Request URI string.
Definition http.h:222
struct http_request_content content
Content descriptor.
Definition http.h:228
struct http_authentication * auth
Authentication scheme (if any).
Definition http.h:305
size_t len
Content length (may be zero).
Definition http.h:271
struct http_content_encoding * encoding
Content encoding.
Definition http.h:273
An HTTP response header.
Definition http.h:372
struct http_transfer_encoding * encoding
Transfer encoding.
Definition http.h:265
unsigned int flags
Flags.
Definition http.h:358
struct http_response_content content
Content descriptor.
Definition http.h:352
struct http_response_auth auth
Authorization descriptor.
Definition http.h:354
unsigned int retry_after
Retry delay (in seconds).
Definition http.h:356
unsigned int status
Status code.
Definition http.h:340
struct line_buffer headers
Raw response header lines.
Definition http.h:335
int rc
Return status code.
Definition http.h:346
const char * location
Redirection location.
Definition http.h:348
struct http_response_transfer transfer
Transfer descriptor.
Definition http.h:350
HTTP transaction state.
Definition http.h:399
int(* tx)(struct http_transaction *http)
Transmit data.
Definition http.h:405
void(* close)(struct http_transaction *http, int rc)
Server connection closed.
Definition http.h:419
int(* rx)(struct http_transaction *http, struct io_buffer **iobuf)
Receive data.
Definition http.h:412
An HTTP transaction.
Definition http.h:423
struct refcnt refcnt
Reference count.
Definition http.h:425
struct retry_timer watchdog
Idle connection watchdog timer.
Definition http.h:439
size_t remaining
Chunk length remaining.
Definition http.h:455
struct http_response response
Response.
Definition http.h:446
struct process process
Transmit process.
Definition http.h:435
struct retry_timer retry
Reconnection timer.
Definition http.h:437
size_t len
Accumulated transfer-decoded length.
Definition http.h:453
struct uri * uri
Request URI.
Definition http.h:442
struct interface conn
Server connection.
Definition http.h:433
struct line_buffer linebuf
Temporary line buffer.
Definition http.h:448
struct interface transfer
Transfer-decoded interface.
Definition http.h:431
struct interface content
Content-decoded interface.
Definition http.h:429
struct http_request request
Request.
Definition http.h:444
struct interface xfer
Data transfer interface.
Definition http.h:427
struct http_state * state
Transaction state.
Definition http.h:451
An HTTP transfer encoding.
Definition http.h:466
struct http_state state
Receive data state.
Definition http.h:476
int(* init)(struct http_transaction *http)
Initialise transfer encoding.
Definition http.h:474
const char * name
Name.
Definition http.h:468
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
A line buffer.
Definition linebuf.h:17
size_t len
Length of buffered data.
Definition linebuf.h:21
char * data
Data buffer.
Definition linebuf.h:19
A request parameter.
Definition params.h:31
A request parameter list.
Definition params.h:17
const char * method
Request method.
Definition params.h:25
A process descriptor.
Definition process.h:32
A process.
Definition process.h:18
A data structure for storing profiling information.
Definition profile.h:27
A reference counter.
Definition refcnt.h:27
A retry timer.
Definition retry.h:22
A Uniform Resource Identifier.
Definition uri.h:65
const char * epath
Path (with original URI encoding).
Definition uri.h:83
struct parameters * params
Request parameters.
Definition uri.h:89
const char * host
Host name.
Definition uri.h:77
const char * scheme
Scheme.
Definition uri.h:69
const char * equery
Query (with original URI encoding).
Definition uri.h:85
const char * port
Port number.
Definition uri.h:79
A data transfer buffer.
Definition xferbuf.h:21
Data transfer metadata.
Definition xfer.h:23
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
size_t format_uri(const struct uri *uri, char *buf, size_t len)
Format URI.
Definition uri.c:473
size_t uri_encode_string(unsigned int field, const char *string, char *buf, ssize_t len)
Encode URI field string.
Definition uri.c:236
struct uri * parse_uri(const char *uri_string)
Parse URI.
Definition uri.c:297
struct uri * resolve_uri(const struct uri *base_uri, struct uri *relative_uri)
Resolve base+relative URI.
Definition uri.c:696
Uniform Resource Identifiers.
static struct uri * uri_get(struct uri *uri)
Increment URI reference count.
Definition uri.h:195
static void uri_put(struct uri *uri)
Decrement URI reference count.
Definition uri.h:206
const char product_version[]
Product version string.
Definition version.c:72
int ssnprintf(char *buf, ssize_t ssize, const char *fmt,...)
Version of vsnprintf() that accepts a signed buffer size.
Definition vsprintf.c:421
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383
printf() and friends
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
int xfer_redirect(struct interface *intf, int type,...)
Send redirection event.
Definition xfer.c:239
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition xfer.c:159
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147
int xfer_seek(struct interface *intf, off_t offset)
Seek to position.
Definition xfer.c:352
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition xfer.c:256
Data transfer interfaces.
struct xfer_buffer * xfer_buffer(struct interface *intf)
Get underlying data transfer buffer.
Definition xferbuf.c:352
Data transfer buffer.