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