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