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