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 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 FILE_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 */
114 static struct profiler http_rx_profiler __profiler = { .name = "http.rx" };
115 
116 /** Data transfer profiler */
117 static struct profiler http_xfer_profiler __profiler = { .name = "http.xfer" };
118 
119 /** Human-readable error messages */
120 struct errortab http_errors[] __errortab = {
124 };
125 
126 static struct http_state http_request;
127 static struct http_state http_headers;
128 static struct http_state http_trailers;
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  */
168 static 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  */
196 char * 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  */
267 static 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  */
283 static 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  */
303 static 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  */
314 static inline void http_watchdog ( struct http_transaction *http ) {
315 
316  /* (Re)start watchdog timer */
317  start_timer_fixed ( &http->watchdog,
319 }
320 
321 /**
322  * Reopen stale HTTP connection
323  *
324  * @v http HTTP transaction
325  */
326 static 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  */
360 static void http_retry_expired ( struct retry_timer *retry,
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  */
390 static 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  */
428 static 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  */
467 static 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  */
487 static 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  */
519 static 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 */
585 };
586 
587 /** HTTP data transfer interface descriptor */
589  INTF_DESC_PASSTHRU ( struct http_transaction, xfer,
590  http_xfer_operations, content );
591 
592 /** HTTP content-decoded interface operations */
598 };
599 
600 /** HTTP content-decoded interface descriptor */
602  INTF_DESC_PASSTHRU ( struct http_transaction, content,
603  http_content_operations, xfer );
604 
605 /** HTTP transfer-decoded interface operations */
608 };
609 
610 /** HTTP transfer-decoded interface descriptor */
612  INTF_DESC_PASSTHRU ( struct http_transaction, transfer,
613  http_transfer_operations, conn );
614 
615 /** HTTP server connection interface operations */
621 };
622 
623 /** HTTP server connection interface descriptor */
625  INTF_DESC_PASSTHRU ( struct http_transaction, conn,
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  */
642 int 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  */
741 static 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  */
785 static 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 */
791  if ( http->response.flags & HTTP_RESPONSE_KEEPALIVE )
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  */
877 static int http_format_headers ( struct http_transaction *http, char *buf,
878  size_t len ) {
879  struct parameters *params = http->uri->params;
880  struct http_request_header *header;
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  */
951 static 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 "*/
959 struct 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 */
980 struct 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 */
1001 struct 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  */
1014 static 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  */
1042 static int http_format_content_type ( struct http_transaction *http,
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 */
1054 struct 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 */
1079 struct http_request_header http_request_content_length __http_request_header = {
1080  .name = "Content-Length",
1081  .format = http_format_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 */
1111 struct http_request_header http_request_accept_encoding __http_request_header ={
1112  .name = "Accept-Encoding",
1113  .format = http_format_accept_encoding,
1114 };
1115 
1116 /**
1117  * Transmit request
1118  *
1119  * @v http HTTP transaction
1120  * @ret rc Return status code
1121  */
1122 static 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 */
1161  empty_line_buffer ( &http->response.headers );
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 */
1177 static 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  */
1196 static 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  */
1272 static int http_parse_header ( struct http_transaction *http, char *line ) {
1273  struct http_response_header *header;
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  */
1308 static 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  */
1346 static 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 */
1354 struct 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 */
1384 struct http_response_header
1385 http_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  */
1397 static 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 */
1412 struct 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 */
1443 struct http_response_header
1444 http_response_content_length __http_response_header = {
1445  .name = "Content-Length",
1446  .parse = http_parse_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 */
1484 struct http_response_header
1485 http_response_content_encoding __http_response_header = {
1486  .name = "Content-Encoding",
1487  .parse = http_parse_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  */
1497 static int http_parse_retry_after ( struct http_transaction *http,
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 */
1521 struct 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  */
1533 static 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 */
1594 static 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  */
1612 static int http_init_transfer_identity ( struct http_transaction *http ) {
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  */
1681  if ( http->response.flags & HTTP_RESPONSE_CONTENT_LEN ) {
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  */
1720 static int http_init_transfer_chunked ( struct http_transaction *http ) {
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  */
1736 static 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  */
1782 static 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  */
1847 static int http_rx_transfer_chunked ( struct http_transaction *http,
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 */
1859 struct 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  */
1882 static 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 */
1907 static 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  */
1927 static 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  */
1984 int 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 */
2041 REQUIRE_OBJECT ( config_http );
struct interface xfer
Data transfer interface.
Definition: http.h:420
A process.
Definition: process.h:18
#define iob_pull(iobuf, len)
Definition: iobuf.h:107
const char * equery
Query (with original URI encoding)
Definition: uri.h:85
An object interface operation.
Definition: interface.h:18
#define ENOENT_404
Definition: httpcore.c:91
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1986
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition: xfer.c:147
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:250
static struct profiler http_rx_profiler __profiler
Receive profiler.
Definition: httpcore.c:114
#define EINFO_EIO_4XX
Definition: httpcore.c:86
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:344
Content length specified.
Definition: http.h:359
#define iob_put(iobuf, len)
Definition: iobuf.h:125
static void http_watchdog_expired(struct retry_timer *watchdog, int over __unused)
Handle idle connection watchdog timer expiry.
Definition: httpcore.c:375
Error message tables.
#define TICKS_PER_SEC
Number of ticks per second.
Definition: timer.h:16
Data transfer metadata.
Definition: xfer.h:23
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:279
struct pci_range range
PCI bus:dev.fn address range.
Definition: pcicloud.c:40
unsigned int flags
Flags.
Definition: http.h:351
static void uri_put(struct uri *uri)
Decrement URI reference count.
Definition: uri.h:206
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition: xfer.c:256
void(* close)(struct http_transaction *http, int rc)
Server connection closed.
Definition: http.h:412
size_t start
Range start.
Definition: http.h:138
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:485
size_t uri_encode_string(unsigned int field, const char *string, char *buf, ssize_t len)
Encode URI field string.
Definition: uri.c:236
const char * host
Server host name.
Definition: http.h:217
static struct uri * uri_get(struct uri *uri)
Increment URI reference count.
Definition: uri.h:195
static struct interface_operation http_conn_operations[]
HTTP server connection interface operations.
Definition: httpcore.c:616
struct http_method http_head
HTTP HEAD method.
Definition: httpcore.c:139
#define EPERM_403
Definition: httpcore.c:100
HTTP request range descriptor.
Definition: http.h:136
#define for_each_param(param, params)
Iterate over all request parameters in a list.
Definition: params.h:84
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:65
Error codes.
A data transfer buffer.
Definition: xferbuf.h:19
struct interface conn
Server connection.
Definition: http.h:426
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:153
static void http_close(struct http_transaction *http, int rc)
Close HTTP transaction.
Definition: httpcore.c:283
const char * name
Header name (e.g.
Definition: http.h:229
static struct interface_descriptor http_transfer_desc
HTTP transfer-decoded interface descriptor.
Definition: httpcore.c:611
static int http_redirect(struct http_transaction *http, const char *location)
Redirect HTTP transaction.
Definition: httpcore.c:741
uint32_t type
Operating system type.
Definition: ena.h:12
static int http_parse_header(struct http_transaction *http, char *line)
Parse HTTP header.
Definition: httpcore.c:1272
static int http_parse_headers(struct http_transaction *http)
Parse HTTP response headers.
Definition: httpcore.c:1308
#define __einfo_errortab(einfo)
Definition: errortab.h:24
#define EPIPE
Broken pipe.
Definition: errno.h:620
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
Retry timers.
A request parameter list.
Definition: params.h:17
static int http_rx_trailers(struct http_transaction *http, struct io_buffer **iobuf)
Handle received HTTP trailer.
Definition: httpcore.c:1882
HTTP transaction state.
Definition: http.h:392
struct line_buffer linebuf
Temporary line buffer.
Definition: http.h:441
printf() and friends
static int http_tx_request(struct http_transaction *http)
Transmit request.
Definition: httpcore.c:1122
static struct interface_descriptor http_content_desc
HTTP content-decoded interface descriptor.
Definition: httpcore.c:601
struct http_request_header http_request_host __http_request_header
HTTP "Host" header ".
Definition: httpcore.c:959
static struct http_transfer_encoding http_transfer_identity
Identity transfer encoding.
Definition: httpcore.c:129
#define DBGC(...)
Definition: compiler.h:505
int(* tx)(struct http_transaction *http)
Transmit data.
Definition: http.h:398
struct uri * uri
Request URI.
Definition: http.h:435
A process descriptor.
Definition: process.h:32
static struct xfer_buffer * http_content_buffer(struct http_transaction *http)
Get underlying data transfer buffer.
Definition: httpcore.c:520
A retry timer.
Definition: retry.h:22
__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
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:108
static int http_parse_connection(struct http_transaction *http, char *line)
Parse HTTP "Connection" header.
Definition: httpcore.c:1397
unsigned long long uint64_t
Definition: stdint.h:13
const char * location
Redirection location.
Definition: http.h:341
int strcasecmp(const char *first, const char *second)
Compare case-insensitive strings.
Definition: string.c:209
An HTTP method.
Definition: http.h:100
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:159
struct http_state * state
Transaction state.
Definition: http.h:444
static int http_format_connection(struct http_transaction *http __unused, char *buf, size_t len)
Construct HTTP "Connection" header.
Definition: httpcore.c:993
REQUIRE_OBJECT(config_http)
REQUIRING_SYMBOL(http_open)
An HTTP authentication scheme.
Definition: http.h:519
iPXE timers
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
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition: process.h:98
This protocol can be used on any device handle to obtain generic path/location information concerning...
Definition: DevicePath.h:46
EFI_DEVICE_PATH_PROTOCOL * efi_uri_path(struct uri *uri)
Construct EFI device path for URI.
Definition: efi_path.c:469
uint8_t method
Definition: ib_mad.h:15
An HTTP request header.
Definition: http.h:227
Character types.
void intfs_shutdown(int rc,...)
Shut down multiple object interfaces.
Definition: interface.c:327
A data structure for storing profiling information.
Definition: profile.h:27
#define EIO_OTHER
Definition: httpcore.c:79
Uniform Resource Identifiers.
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition: profile.h:174
An HTTP content encoding.
Definition: http.h:487
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition: string.c:187
void process_del(struct process *process)
Remove process from process list.
Definition: process.c:80
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:131
struct http_response_auth auth
Authorization descriptor.
Definition: http.h:347
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:117
struct http_request_range range
Range descriptor.
Definition: http.h:219
void intfs_restart(int rc,...)
Shut down and restart multiple object interfaces.
Definition: interface.c:387
#define EXDEV
Improper link.
Definition: errno.h:685
int(* rx)(struct http_transaction *http, struct io_buffer **iobuf)
Receive data.
Definition: http.h:405
#define ECANCELED
Operation canceled.
Definition: errno.h:344
#define ENOTSUP
Operation not supported.
Definition: errno.h:590
static int http_format_content_type(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Content-Type" header.
Definition: httpcore.c:1042
Data transfer interfaces.
A reference counter.
Definition: refcnt.h:27
struct http_request request
Request.
Definition: http.h:437
const char * port
Port number.
Definition: uri.h:79
static struct interface_operation http_content_operations[]
HTTP content-decoded interface operations.
Definition: httpcore.c:593
static void http_watchdog(struct http_transaction *http)
Hold off HTTP idle connection watchdog timer.
Definition: httpcore.c:314
int http_connect(struct interface *xfer, struct uri *uri)
Connect to an HTTP server.
Definition: httpconn.c:237
int ssnprintf(char *buf, ssize_t ssize, const char *fmt,...)
Version of vsnprintf() that accepts a signed buffer size.
Definition: vsprintf.c:421
int(* authenticate)(struct http_transaction *http)
Perform authentication.
Definition: http.h:534
char * data
Data buffer.
Definition: linebuf.h:19
struct http_transfer_encoding * encoding
Transfer encoding.
Definition: http.h:258
#define EINVAL_STATUS
Definition: httpcore.c:67
Keep connection alive after close.
Definition: http.h:357
#define ENOMEM
Not enough space.
Definition: errno.h:535
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:217
#define EINFO_EIO_5XX
Definition: httpcore.c:89
struct http_transfer_encoding http_transfer_chunked __http_transfer_encoding
Chunked transfer encoding.
Definition: httpcore.c:1859
const char * scheme
Scheme.
Definition: uri.h:69
void * memcpy(void *dest, const void *src, size_t len) __nonnull
const char * name
Name.
Definition: profile.h:29
u32 version
Driver version.
Definition: ath9k_hw.c:1985
struct http_response response
Response.
Definition: http.h:439
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
static EFI_DEVICE_PATH_PROTOCOL * http_efi_describe(struct http_transaction *http)
Describe as an EFI device path.
Definition: httpcore.c:571
static int http_parse_transfer_encoding(struct http_transaction *http, char *line)
Parse HTTP "Transfer-Encoding" header.
Definition: httpcore.c:1366
An HTTP transaction.
Definition: http.h:416
Hyper Text Transport Protocol.
Assertions.
static struct interface_operation http_xfer_operations[]
HTTP data transfer interface operations.
Definition: httpcore.c:577
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
Request parameters.
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:36
const char * uri
Request URI string.
Definition: http.h:215
An object interface.
Definition: interface.h:125
static int http_parse_content_encoding(struct http_transaction *http, char *line)
Parse HTTP "Content-Encoding" header.
Definition: httpcore.c:1456
Location is a URI.
Definition: open.h:28
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
static int http_rx_transfer_chunked(struct http_transaction *http, struct io_buffer **iobuf)
Handle received chunked data.
Definition: httpcore.c:1847
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
size_t len
Accumulated transfer-decoded length.
Definition: http.h:446
#define HTTP_RESPONSE_HEADERS
HTTP response header table.
Definition: http.h:378
struct http_request_auth auth
Authentication descriptor.
Definition: http.h:223
struct http_response_content content
Content descriptor.
Definition: http.h:345
ring len
Length.
Definition: dwmac.h:231
void empty_line_buffer(struct line_buffer *linebuf)
Discard line buffer contents.
Definition: linebuf.c:66
size_t len
Length of buffered data.
Definition: linebuf.h:21
static unsigned int count
Number of entries.
Definition: dwmac.h:225
__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
size_t format_uri(const struct uri *uri, char *buf, size_t len)
Format URI.
Definition: uri.c:472
void pool_reopen(struct interface *intf)
Reopen a defunct connection.
Definition: pool.c:52
const char * name
Name.
Definition: http.h:489
static void profile_start(struct profiler *profiler)
Start profiling.
Definition: profile.h:161
Profiling.
int http_open_uri(struct interface *xfer, struct uri *uri)
Open HTTP transaction for simple URI.
Definition: httpcore.c:1984
struct http_request_content content
Content descriptor.
Definition: http.h:221
#define EIO_CONTENT_LENGTH
Definition: httpcore.c:82
const char * name
Method name (e.g.
Definition: http.h:102
struct parameters * params
Request parameters.
Definition: uri.h:89
HTTP request content descriptor.
Definition: http.h:144
int xfer_seek(struct interface *intf, off_t offset)
Seek to position.
Definition: xfer.c:352
void process_add(struct process *process)
Add process to process list.
Definition: process.c:60
static int http_parse_location(struct http_transaction *http, char *line)
Parse HTTP "Location" header.
Definition: httpcore.c:1346
#define EFI_INTF_OP
Definition: efi.h:374
static struct interface_descriptor http_conn_desc
HTTP server connection interface descriptor.
Definition: httpcore.c:624
An object interface descriptor.
Definition: interface.h:56
struct http_content_encoding * encoding
Content encoding.
Definition: http.h:266
#define iob_unput(iobuf, len)
Definition: iobuf.h:140
struct http_method http_get
HTTP GET method.
Definition: httpcore.c:144
Block devices.
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
FILE_SECBOOT(PERMITTED)
struct http_authentication * auth
Authentication scheme (if any)
Definition: http.h:190
ACPI data structures.
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
#define EACCES_401
Definition: httpcore.c:64
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
const char * name
Header name (e.g.
Definition: http.h:367
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:272
size_t len
Content length (may be zero)
Definition: http.h:264
struct interface content
Content-decoded interface.
Definition: http.h:422
struct process process
Transmit process.
Definition: http.h:428
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:160
struct hv_monitor_parameter param[4][32]
Parameters.
Definition: hyperv.h:24
int rc
Return status code.
Definition: http.h:339
unsigned int status
Status code.
Definition: http.h:333
static struct interface_descriptor http_xfer_desc
HTTP data transfer interface descriptor.
Definition: httpcore.c:588
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:33
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:386
struct interface transfer
Transfer-decoded interface.
Definition: http.h:424
int isspace(int character)
Check to see if character is a space.
Definition: ctype.c:42
#define ENOTSUP_TRANSFER
Definition: httpcore.c:97
struct http_response_header http_response_location __http_response_header
HTTP "Location" header.
Definition: httpcore.c:1354
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:195
const char * type
Content type (if any)
Definition: http.h:146
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
uint64_t lba
Starting block number.
Definition: int13.h:22
#define EINVAL_HEADER
Definition: httpcore.c:70
Processes.
const char product_version[]
Product version string.
Definition: version.c:71
char * buffered_line(struct line_buffer *linebuf)
Retrieve buffered-up line.
Definition: linebuf.c:46
struct xfer_buffer * xfer_buffer(struct interface *intf)
Get underlying data transfer buffer.
Definition: xferbuf.c:306
unsigned char uint8_t
Definition: stdint.h:10
#define EPROTO_UNSOLICITED
Definition: httpcore.c:103
static int http_rx_headers(struct http_transaction *http, struct io_buffer **iobuf)
Handle received HTTP headers.
Definition: httpcore.c:1533
static int http_parse_retry_after(struct http_transaction *http, char *line)
Parse HTTP "Retry-After" header.
Definition: httpcore.c:1497
#define HTTP_RETRY_SECONDS
Retry delay used when we cannot understand the Retry-After header.
Definition: httpcore.c:108
Data transfer interface opening.
EFI device paths.
static int http_rx_transfer_identity(struct http_transaction *http, struct io_buffer **iobuf)
Handle received data.
Definition: httpcore.c:1631
char * http_token(char **line, char **value)
Get HTTP response token.
Definition: httpcore.c:196
#define HTTP_TRANSFER_ENCODINGS
HTTP transfer encoding table.
Definition: http.h:473
#define EINVAL_CONTENT_LENGTH
Definition: httpcore.c:73
struct line_buffer headers
Raw response header lines.
Definition: http.h:328
Version number.
static int http_format_host(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Host" header.
Definition: httpcore.c:951
uint32_t next
Next descriptor address.
Definition: dwmac.h:22
const char * host
Host name.
Definition: uri.h:77
#define PARAMETER_FORM
Request parameter is a form parameter.
Definition: params.h:41
static int http_format_content_length(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Content-Length" header.
Definition: httpcore.c:1067
u8 token
Definition: CIB_PRM.h:42
#define EIO_5XX
Definition: httpcore.c:88
uint8_t status
Status.
Definition: ena.h:16
static size_t http_form_params(struct parameters *params, char *buf, size_t len)
Construct HTTP form parameter list.
Definition: httpcore.c:1927
const void * data
Content data (if any)
Definition: http.h:148
static int http_init_transfer_chunked(struct http_transaction *http)
Initialise transfer encoding.
Definition: httpcore.c:1720
#define EINFO_ENOENT_404
Definition: httpcore.c:92
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition: retry.c:65
size_t len
Range length, or zero for no range request.
Definition: http.h:140
size_t len
Content length.
Definition: http.h:150
static void http_close_transfer_identity(struct http_transaction *http, int rc)
Handle server connection close.
Definition: httpcore.c:1670
struct http_response_transfer transfer
Transfer descriptor.
Definition: http.h:343
#define EINVAL_CHUNK_LENGTH
Definition: httpcore.c:76
static int http_rx_chunk_len(struct http_transaction *http, struct io_buffer **iobuf)
Handle received chunk length.
Definition: httpcore.c:1736
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:118
static struct process_descriptor http_process_desc
HTTP process descriptor.
Definition: httpcore.c:629
EFI_DEVICE_PATH_PROTOCOL * efi_describe(struct interface *intf)
Describe object as an EFI device path.
Definition: efi_path.c:920
#define DBGC2(...)
Definition: compiler.h:522
static int http_transfer_complete(struct http_transaction *http)
Handle successful transfer completion.
Definition: httpcore.c:785
#define HTTP_REQUEST_HEADERS
HTTP request header table.
Definition: http.h:242
struct http_authentication * auth
Authentication scheme (if any)
Definition: http.h:298
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
void * data
Start of data.
Definition: iobuf.h:53
A line buffer.
Definition: linebuf.h:17
static int http_parse_status(struct http_transaction *http, char *line)
Parse HTTP status line.
Definition: httpcore.c:1196
static void http_close_error(struct http_transaction *http, int rc)
Close HTTP transaction with error (even if none specified)
Definition: httpcore.c:303
struct refcnt refcnt
Reference count.
Definition: http.h:418
struct ena_llq_option header
Header locations.
Definition: ena.h:16
struct http_method * method
Method.
Definition: http.h:213
static void http_reopen(struct http_transaction *http)
Reopen stale HTTP connection.
Definition: httpcore.c:326
Reference counting.
static struct interface_operation http_transfer_operations[]
HTTP transfer-decoded interface operations.
Definition: httpcore.c:606
uint8_t data[48]
Additional event data.
Definition: ena.h:22
static int http_init_transfer_identity(struct http_transaction *http)
Initialise transfer encoding.
Definition: httpcore.c:1612
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
const char * name
Name (e.g.
Definition: http.h:521
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
const char * epath
Path (with original URI encoding)
Definition: uri.h:83
#define __weak
Declare a function as weak (use before the definition)
Definition: compiler.h:219
#define HTTP_WATCHDOG_SECONDS
Idle connection watchdog timeout.
Definition: httpcore.c:111
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:383
size_t remaining
Chunk length remaining.
Definition: http.h:448
A Uniform Resource Identifier.
Definition: uri.h:65
Transaction may be retried on failure.
Definition: http.h:361
#define INTF_DESC_PASSTHRU(object_type, intf, operations, passthru)
Define an object interface descriptor with pass-through interface.
Definition: interface.h:98
An HTTP request.
Definition: http.h:211
A request parameter.
Definition: params.h:29
#define EIO_4XX
Definition: httpcore.c:85
static void http_free(struct refcnt *refcnt)
Free HTTP transaction.
Definition: httpcore.c:267
int line_buffer(struct line_buffer *linebuf, const char *data, size_t len)
Buffer up received data by lines.
Definition: linebuf.c:92
signed long ssize_t
Definition: stdint.h:7
struct uri * resolve_uri(const struct uri *base_uri, struct uri *relative_uri)
Resolve base+relative URI.
Definition: uri.c:695
static void http_retry_expired(struct retry_timer *retry, int over __unused)
Handle connection retry timer expiry.
Definition: httpcore.c:360
static struct http_state http_headers
HTTP response headers state.
Definition: httpcore.c:127
static struct http_state http_request
HTTP request state.
Definition: httpcore.c:126
uint8_t meta
Metadata flags.
Definition: ena.h:14
static void http_step(struct http_transaction *http)
HTTP transmit process.
Definition: httpcore.c:390
int(* init)(struct http_transaction *http)
Initialise transfer encoding.
Definition: http.h:467
void pool_recycle(struct interface *intf)
Recycle this connection after closing.
Definition: pool.c:42
int block_read_capacity(struct interface *control, struct interface *data)
Read block device capacity.
Definition: blockdev.c:106
Line buffering.
int(* supported)(struct http_transaction *http)
Check if content encoding is supported for this request.
Definition: http.h:495
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:204
const char * name
Name.
Definition: http.h:461
struct http_state state
Receive data state.
Definition: http.h:469
An HTTP transfer encoding.
Definition: http.h:459
static int http_format_headers(struct http_transaction *http, char *buf, size_t len)
Construct HTTP request headers.
Definition: httpcore.c:877
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_rx_chunk_data(struct http_transaction *http, struct io_buffer **iobuf)
Handle received chunk data.
Definition: httpcore.c:1782
static int http_format_range(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Range" header.
Definition: httpcore.c:1014
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:670
#define PARAMETER_HEADER
Request parameter is a header parameter.
Definition: params.h:44
String functions.
struct retry_timer retry
Reconnection timer.
Definition: http.h:430
struct http_method http_post
HTTP POST method.
Definition: httpcore.c:149
int(* init)(struct http_transaction *http)
Initialise content encoding.
Definition: http.h:501
unsigned int retry_after
Retry delay (in seconds)
Definition: http.h:349
static int http_format_accept_encoding(struct http_transaction *http, char *buf, size_t len)
Construct HTTP "Accept-Encoding" header.
Definition: httpcore.c:1092
Data transfer buffer.
struct errortab http_errors [] __errortab
Human-readable error messages.
Definition: httpcore.c:120
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:107
static int http_parse_content_length(struct http_transaction *http, char *line)
Parse HTTP "Content-Length" header.
Definition: httpcore.c:1424
An HTTP response header.
Definition: http.h:365
String functions.
struct uri * parse_uri(const char *uri_string)
Parse URI.
Definition: uri.c:297
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
void * memset(void *dest, int character, size_t len) __nonnull
static struct http_state http_trailers
HTTP response trailers state.
Definition: httpcore.c:128
static void http_conn_close(struct http_transaction *http, int rc)
Handle server connection close.
Definition: httpcore.c:467
#define HTTP_CONTENT_ENCODINGS
HTTP content encoding table.
Definition: http.h:505
A persistent I/O buffer.
Definition: iobuf.h:38
struct retry_timer watchdog
Idle connection watchdog timer.
Definition: http.h:432
int xfer_redirect(struct interface *intf, int type,...)
Send redirection event.
Definition: xfer.c:239