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