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