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