소스 검색

[http] Support read-only HTTP block devices

Provide support for HTTP range requests, and expose this functionality
via the iPXE block device API.  This allows SAN booting from a root
path such as:

    sanboot http://boot.ipxe.org/freedos/fdfullcd.iso

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 년 전
부모
커밋
2988b26653
1개의 변경된 파일308개의 추가작업 그리고 59개의 파일을 삭제
  1. 308
    59
      src/net/tcp/http.c

+ 308
- 59
src/net/tcp/http.c 파일 보기

@@ -44,14 +44,23 @@ FILE_LICENCE ( GPL2_OR_LATER );
44 44
 #include <ipxe/linebuf.h>
45 45
 #include <ipxe/features.h>
46 46
 #include <ipxe/base64.h>
47
+#include <ipxe/blockdev.h>
48
+#include <ipxe/acpi.h>
47 49
 #include <ipxe/http.h>
48 50
 
49 51
 FEATURE ( FEATURE_PROTOCOL, "HTTP", DHCP_EB_FEATURE_HTTP, 1 );
50 52
 
51
-/** HTTP transmission state */
52
-enum http_tx_state {
53
-	HTTP_TX_REQUEST = 0,
54
-	HTTP_TX_DONE,
53
+/** Block size used for HTTP block device request */
54
+#define HTTP_BLKSIZE 512
55
+
56
+/** HTTP flags */
57
+enum http_flags {
58
+	/** Request is waiting to be transmitted */
59
+	HTTP_TX_PENDING = 0x0001,
60
+	/** Fetch header only */
61
+	HTTP_HEAD_ONLY = 0x0002,
62
+	/** Keep connection alive */
63
+	HTTP_KEEPALIVE = 0x0004,
55 64
 };
56 65
 
57 66
 /** HTTP receive state */
@@ -61,6 +70,7 @@ enum http_rx_state {
61 70
 	HTTP_RX_CHUNK_LEN,
62 71
 	HTTP_RX_DATA,
63 72
 	HTTP_RX_TRAILER,
73
+	HTTP_RX_IDLE,
64 74
 	HTTP_RX_DEAD,
65 75
 };
66 76
 
@@ -73,31 +83,38 @@ struct http_request {
73 83
 	struct refcnt refcnt;
74 84
 	/** Data transfer interface */
75 85
 	struct interface xfer;
86
+	/** Partial transfer interface */
87
+	struct interface partial;
76 88
 
77 89
 	/** URI being fetched */
78 90
 	struct uri *uri;
79 91
 	/** Transport layer interface */
80 92
 	struct interface socket;
81 93
 
94
+	/** Flags */
95
+	unsigned int flags;
96
+	/** Starting offset of partial transfer (if applicable) */
97
+	size_t partial_start;
98
+	/** Length of partial transfer (if applicable) */
99
+	size_t partial_len;
100
+
82 101
 	/** TX process */
83 102
 	struct process process;
84
-	/** TX state */
85
-	enum http_tx_state tx_state;
86 103
 
87
-	/** HTTP response code */
88
-	unsigned int response;
89
-	/** HTTP Content-Length */
90
-	size_t content_length;
91
-	/** HTTP is using Transfer-Encoding: chunked */
92
-	int chunked;
93
-	/** Current chunk length */
94
-	size_t chunk_len;
95
-	/** Received length */
96
-	size_t rx_len;
97 104
 	/** RX state */
98 105
 	enum http_rx_state rx_state;
106
+	/** Received length */
107
+	size_t rx_len;
108
+	/** Length remaining (or 0 if unknown) */
109
+	size_t remaining;
110
+	/** HTTP is using Transfer-Encoding: chunked */
111
+	int chunked;
112
+	/** Current chunk length remaining (if applicable) */
113
+	size_t chunk_remaining;
99 114
 	/** Line buffer for received header lines */
100 115
 	struct line_buffer linebuf;
116
+	/** Receive data buffer (if applicable) */
117
+	userptr_t rx_buffer;
101 118
 };
102 119
 
103 120
 /**
@@ -115,12 +132,12 @@ static void http_free ( struct refcnt *refcnt ) {
115 132
 };
116 133
 
117 134
 /**
118
- * Mark HTTP request as complete
135
+ * Close HTTP request
119 136
  *
120 137
  * @v http		HTTP request
121 138
  * @v rc		Return status code
122 139
  */
123
-static void http_done ( struct http_request *http, int rc ) {
140
+static void http_close ( struct http_request *http, int rc ) {
124 141
 
125 142
 	/* Prevent further processing of any current packet */
126 143
 	http->rx_state = HTTP_RX_DEAD;
@@ -128,11 +145,11 @@ static void http_done ( struct http_request *http, int rc ) {
128 145
 	/* If we had a Content-Length, and the received content length
129 146
 	 * isn't correct, flag an error
130 147
 	 */
131
-	if ( http->content_length &&
132
-	     ( http->content_length != http->rx_len ) ) {
148
+	if ( http->remaining != 0 ) {
133 149
 		DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n",
134
-		       http, http->rx_len, http->content_length );
135
-		rc = -EIO;
150
+		       http, http->rx_len, ( http->rx_len + http->remaining ) );
151
+		if ( rc == 0 )
152
+			rc = -EIO;
136 153
 	}
137 154
 
138 155
 	/* Remove process */
@@ -140,9 +157,40 @@ static void http_done ( struct http_request *http, int rc ) {
140 157
 
141 158
 	/* Close all data transfer interfaces */
142 159
 	intf_shutdown ( &http->socket, rc );
160
+	intf_shutdown ( &http->partial, rc );
143 161
 	intf_shutdown ( &http->xfer, rc );
144 162
 }
145 163
 
164
+/**
165
+ * Mark HTTP request as completed successfully
166
+ *
167
+ * @v http		HTTP request
168
+ */
169
+static void http_done ( struct http_request *http ) {
170
+
171
+	/* If we had a Content-Length, and the received content length
172
+	 * isn't correct, force an error
173
+	 */
174
+	if ( http->remaining != 0 ) {
175
+		http_close ( http, -EIO );
176
+		return;
177
+	}
178
+
179
+	/* Enter idle state */
180
+	http->rx_state = HTTP_RX_IDLE;
181
+	http->rx_len = 0;
182
+	assert ( http->remaining == 0 );
183
+	assert ( http->chunked == 0 );
184
+	assert ( http->chunk_remaining == 0 );
185
+
186
+	/* Close partial transfer interface */
187
+	intf_restart ( &http->partial, 0 );
188
+
189
+	/* Close everything unless we are keeping the connection alive */
190
+	if ( ! ( http->flags & HTTP_KEEPALIVE ) )
191
+		http_close ( http, 0 );
192
+}
193
+
146 194
 /**
147 195
  * Convert HTTP response code to return status code
148 196
  *
@@ -152,6 +200,7 @@ static void http_done ( struct http_request *http, int rc ) {
152 200
 static int http_response_to_rc ( unsigned int response ) {
153 201
 	switch ( response ) {
154 202
 	case 200:
203
+	case 206:
155 204
 	case 301:
156 205
 	case 302:
157 206
 		return 0;
@@ -175,6 +224,7 @@ static int http_response_to_rc ( unsigned int response ) {
175 224
  */
176 225
 static int http_rx_response ( struct http_request *http, char *response ) {
177 226
 	char *spc;
227
+	unsigned int code;
178 228
 	int rc;
179 229
 
180 230
 	DBGC ( http, "HTTP %p response \"%s\"\n", http, response );
@@ -187,8 +237,8 @@ static int http_rx_response ( struct http_request *http, char *response ) {
187 237
 	spc = strchr ( response, ' ' );
188 238
 	if ( ! spc )
189 239
 		return -EIO;
190
-	http->response = strtoul ( spc, NULL, 10 );
191
-	if ( ( rc = http_response_to_rc ( http->response ) ) != 0 )
240
+	code = strtoul ( spc, NULL, 10 );
241
+	if ( ( rc = http_response_to_rc ( code ) ) != 0 )
192 242
 		return rc;
193 243
 
194 244
 	/* Move to received headers */
@@ -227,19 +277,40 @@ static int http_rx_location ( struct http_request *http, const char *value ) {
227 277
  */
228 278
 static int http_rx_content_length ( struct http_request *http,
229 279
 				    const char *value ) {
280
+	struct block_device_capacity capacity;
281
+	size_t content_len;
230 282
 	char *endp;
231 283
 
232
-	http->content_length = strtoul ( value, &endp, 10 );
284
+	/* Parse content length */
285
+	content_len = strtoul ( value, &endp, 10 );
233 286
 	if ( *endp != '\0' ) {
234 287
 		DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n",
235 288
 		       http, value );
236 289
 		return -EIO;
237 290
 	}
238 291
 
292
+	/* If we already have an expected content length, and this
293
+	 * isn't it, then complain
294
+	 */
295
+	if ( http->remaining && ( http->remaining != content_len ) ) {
296
+		DBGC ( http, "HTTP %p incorrect Content-Length %zd (expected "
297
+		       "%zd)\n", http, content_len, http->remaining );
298
+		return -EIO;
299
+	}
300
+	if ( ! ( http->flags & HTTP_HEAD_ONLY ) )
301
+		http->remaining = content_len;
302
+
239 303
 	/* Use seek() to notify recipient of filesize */
240
-	xfer_seek ( &http->xfer, http->content_length );
304
+	xfer_seek ( &http->xfer, http->remaining );
241 305
 	xfer_seek ( &http->xfer, 0 );
242 306
 
307
+	/* Report block device capacity if applicable */
308
+	if ( http->flags & HTTP_HEAD_ONLY ) {
309
+		capacity.blocks = ( content_len / HTTP_BLKSIZE );
310
+		capacity.blksize = HTTP_BLKSIZE;
311
+		capacity.max_count = -1U;
312
+		block_capacity ( &http->partial, &capacity );
313
+	}
243 314
 	return 0;
244 315
 }
245 316
 
@@ -309,14 +380,15 @@ static int http_rx_header ( struct http_request *http, char *header ) {
309 380
 	/* An empty header line marks the end of this phase */
310 381
 	if ( ! header[0] ) {
311 382
 		empty_line_buffer ( &http->linebuf );
312
-		if ( http->rx_state == HTTP_RX_HEADER ) {
383
+		if ( ( http->rx_state == HTTP_RX_HEADER ) &&
384
+		     ( ! ( http->flags & HTTP_HEAD_ONLY ) ) ) {
313 385
 			DBGC ( http, "HTTP %p start of data\n", http );
314 386
 			http->rx_state = ( http->chunked ?
315 387
 					   HTTP_RX_CHUNK_LEN : HTTP_RX_DATA );
316 388
 			return 0;
317 389
 		} else {
318 390
 			DBGC ( http, "HTTP %p end of trailer\n", http );
319
-			http_done ( http, 0 );
391
+			http_done ( http );
320 392
 			return 0;
321 393
 		}
322 394
 	}
@@ -358,7 +430,7 @@ static int http_rx_chunk_len ( struct http_request *http, char *length ) {
358 430
 		return 0;
359 431
 
360 432
 	/* Parse chunk length */
361
-	http->chunk_len = strtoul ( length, &endp, 16 );
433
+	http->chunk_remaining = strtoul ( length, &endp, 16 );
362 434
 	if ( *endp != '\0' ) {
363 435
 		DBGC ( http, "HTTP %p invalid chunk length \"%s\"\n",
364 436
 		       http, length );
@@ -366,7 +438,7 @@ static int http_rx_chunk_len ( struct http_request *http, char *length ) {
366 438
 	}
367 439
 
368 440
 	/* Terminate chunked encoding if applicable */
369
-	if ( http->chunk_len == 0 ) {
441
+	if ( http->chunk_remaining == 0 ) {
370 442
 		DBGC ( http, "HTTP %p end of chunks\n", http );
371 443
 		http->chunked = 0;
372 444
 		http->rx_state = HTTP_RX_TRAILER;
@@ -375,8 +447,8 @@ static int http_rx_chunk_len ( struct http_request *http, char *length ) {
375 447
 
376 448
 	/* Use seek() to notify recipient of new filesize */
377 449
 	DBGC ( http, "HTTP %p start of chunk of length %zd\n",
378
-	       http, http->chunk_len );
379
-	xfer_seek ( &http->xfer, ( http->rx_len + http->chunk_len ) );
450
+	       http, http->chunk_remaining );
451
+	xfer_seek ( &http->xfer, ( http->rx_len + http->chunk_remaining ) );
380 452
 	xfer_seek ( &http->xfer, http->rx_len );
381 453
 
382 454
 	/* Start receiving data */
@@ -422,34 +494,60 @@ static int http_socket_deliver ( struct http_request *http,
422 494
 	int rc = 0;
423 495
 
424 496
 	while ( iobuf && iob_len ( iobuf ) ) {
497
+
425 498
 		switch ( http->rx_state ) {
499
+		case HTTP_RX_IDLE:
500
+			/* Receiving any data in this state is an error */
501
+			DBGC ( http, "HTTP %p received %zd bytes while %s\n",
502
+			       http, iob_len ( iobuf ),
503
+			       ( ( http->rx_state == HTTP_RX_IDLE ) ?
504
+				 "idle" : "dead" ) );
505
+			rc = -EPROTO;
506
+			goto done;
426 507
 		case HTTP_RX_DEAD:
427 508
 			/* Do no further processing */
428 509
 			goto done;
429 510
 		case HTTP_RX_DATA:
430 511
 			/* Pass received data to caller */
431 512
 			data_len = iob_len ( iobuf );
432
-			if ( http->chunk_len && ( http->chunk_len < data_len )){
433
-				data_len = http->chunk_len;
513
+			if ( http->chunk_remaining &&
514
+			     ( http->chunk_remaining < data_len ) ) {
515
+				data_len = http->chunk_remaining;
516
+			}
517
+			if ( http->remaining &&
518
+			     ( http->remaining < data_len ) ) {
519
+				data_len = http->remaining;
520
+			}
521
+			if ( http->rx_buffer != UNULL ) {
522
+				/* Copy to partial transfer buffer */
523
+				copy_to_user ( http->rx_buffer, http->rx_len,
524
+					       iobuf->data, data_len );
525
+				iob_pull ( iobuf, data_len );
526
+			} else if ( data_len < iob_len ( iobuf ) ) {
527
+				/* Deliver partial buffer as raw data */
434 528
 				rc = xfer_deliver_raw ( &http->xfer,
435 529
 							iobuf->data, data_len );
436 530
 				iob_pull ( iobuf, data_len );
531
+				if ( rc != 0 )
532
+					goto done;
437 533
 			} else {
438
-				rc = xfer_deliver_iob ( &http->xfer,
439
-							iob_disown ( iobuf ) );
534
+				/* Deliver whole I/O buffer */
535
+				if ( ( rc = xfer_deliver_iob ( &http->xfer,
536
+						 iob_disown ( iobuf ) ) ) != 0 )
537
+					goto done;
440 538
 			}
441
-			if ( rc != 0 )
442
-				goto done;
443
-			if ( http->chunk_len ) {
444
-				http->chunk_len -= data_len;
445
-				if ( http->chunk_len == 0 )
539
+			http->rx_len += data_len;
540
+			if ( http->chunk_remaining ) {
541
+				http->chunk_remaining -= data_len;
542
+				if ( http->chunk_remaining == 0 )
446 543
 					http->rx_state = HTTP_RX_CHUNK_LEN;
447 544
 			}
448
-			http->rx_len += data_len;
449
-			if ( http->content_length &&
450
-			     ( http->rx_len >= http->content_length ) ) {
451
-				http_done ( http, 0 );
452
-				goto done;
545
+			if ( http->remaining ) {
546
+				http->remaining -= data_len;
547
+				if ( ( http->remaining == 0 ) &&
548
+				     ( http->rx_state == HTTP_RX_DATA ) ) {
549
+					http_done ( http );
550
+				}
453 551
 			}
454 552
 			break;
455 553
 		case HTTP_RX_RESPONSE:
@@ -483,11 +581,25 @@ static int http_socket_deliver ( struct http_request *http,
483 581
 
484 582
  done:
485 583
 	if ( rc )
486
-		http_done ( http, rc );
584
+		http_close ( http, rc );
487 585
 	free_iob ( iobuf );
488 586
 	return rc;
489 587
 }
490 588
 
589
+/**
590
+ * Check HTTP socket flow control window
591
+ *
592
+ * @v http		HTTP request
593
+ * @ret len		Length of window
594
+ */
595
+static size_t http_socket_window ( struct http_request *http __unused ) {
596
+
597
+	/* Window is always open.  This is to prevent TCP from
598
+	 * stalling if our parent window is not currently open.
599
+	 */
600
+	return ( ~( ( size_t ) 0 ) );
601
+}
602
+
491 603
 /**
492 604
  * HTTP process
493 605
  *
@@ -507,9 +619,11 @@ static void http_step ( struct http_request *http ) {
507 619
 	int request_len = unparse_uri ( NULL, 0, http->uri,
508 620
 					URI_PATH_BIT | URI_QUERY_BIT );
509 621
 	char request[ request_len + 1 /* NUL */ ];
622
+	char range[48]; /* Enough for two 64-bit integers in decimal */
623
+	int partial;
510 624
 
511 625
 	/* Do nothing if we have already transmitted the request */
512
-	if ( http->tx_state != HTTP_TX_REQUEST )
626
+	if ( ! ( http->flags & HTTP_TX_PENDING ) )
513 627
 		return;
514 628
 
515 629
 	/* Do nothing until socket is ready */
@@ -530,32 +644,151 @@ static void http_step ( struct http_request *http ) {
530 644
 		base64_encode ( user_pw, user_pw_len, user_pw_base64 );
531 645
 	}
532 646
 
647
+	/* Force a HEAD request if we have nowhere to send any received data */
648
+	if ( ( xfer_window ( &http->xfer ) == 0 ) &&
649
+	     ( http->rx_buffer == UNULL ) ) {
650
+		http->flags |= ( HTTP_HEAD_ONLY | HTTP_KEEPALIVE );
651
+	}
652
+
653
+	/* Determine type of request */
654
+	partial = ( http->partial_len != 0 );
655
+	snprintf ( range, sizeof ( range ), "%d-%d", http->partial_start,
656
+		   ( http->partial_start + http->partial_len - 1 ) );
657
+
533 658
 	/* Mark request as transmitted */
534
-	http->tx_state = HTTP_TX_DONE;
659
+	http->flags &= ~HTTP_TX_PENDING;
535 660
 
536 661
 	/* Send GET request */
537 662
 	if ( ( rc = xfer_printf ( &http->socket,
538
-				  "GET %s%s HTTP/1.1\r\n"
663
+				  "%s %s%s HTTP/1.1\r\n"
539 664
 				  "User-Agent: iPXE/" VERSION "\r\n"
540
-				  "%s%s%s"
541 665
 				  "Host: %s\r\n"
666
+				  "%s%s%s%s%s%s%s"
542 667
 				  "\r\n",
543
-				  http->uri->path ? "" : "/",
544
-				  request,
668
+				  ( ( http->flags & HTTP_HEAD_ONLY ) ?
669
+				    "HEAD" : "GET" ),
670
+				  ( http->uri->path ? "" : "/" ),
671
+				  request, host,
672
+				  ( ( http->flags & HTTP_KEEPALIVE ) ?
673
+				    "Connection: Keep-Alive\r\n" : "" ),
674
+				  ( partial ? "Range: bytes=" : "" ),
675
+				  ( partial ? range : "" ),
676
+				  ( partial ? "\r\n" : "" ),
545 677
 				  ( user ?
546 678
 				    "Authorization: Basic " : "" ),
547 679
 				  ( user ? user_pw_base64 : "" ),
548
-				  ( user ? "\r\n" : "" ),
549
-				  host ) ) != 0 ) {
550
-		http_done ( http, rc );
680
+				  ( user ? "\r\n" : "" ) ) ) != 0 ) {
681
+		http_close ( http, rc );
551 682
 	}
552 683
 }
553 684
 
685
+/**
686
+ * Check HTTP data transfer flow control window
687
+ *
688
+ * @v http		HTTP request
689
+ * @ret len		Length of window
690
+ */
691
+static size_t http_xfer_window ( struct http_request *http ) {
692
+
693
+	/* New block commands may be issued only when we are idle */
694
+	return ( ( http->rx_state == HTTP_RX_IDLE ) ? 1 : 0 );
695
+}
696
+
697
+/**
698
+ * Initiate HTTP partial read
699
+ *
700
+ * @v http		HTTP request
701
+ * @v partial		Partial transfer interface
702
+ * @v offset		Starting offset
703
+ * @v buffer		Data buffer
704
+ * @v len		Length
705
+ * @ret rc		Return status code
706
+ */
707
+static int http_partial_read ( struct http_request *http,
708
+			       struct interface *partial,
709
+			       size_t offset, userptr_t buffer, size_t len ) {
710
+
711
+	/* Sanity check */
712
+	if ( http_xfer_window ( http ) == 0 )
713
+		return -EBUSY;
714
+
715
+	/* Initialise partial transfer parameters */
716
+	http->rx_buffer = buffer;
717
+	http->partial_start = offset;
718
+	http->partial_len = len;
719
+	http->remaining = len;
720
+
721
+	/* Schedule request */
722
+	http->rx_state = HTTP_RX_RESPONSE;
723
+	http->flags = ( HTTP_TX_PENDING | HTTP_KEEPALIVE );
724
+	if ( ! len )
725
+		http->flags |= HTTP_HEAD_ONLY;
726
+	process_add ( &http->process );
727
+
728
+	/* Attach to parent interface and return */
729
+	intf_plug_plug ( &http->partial, partial );
730
+
731
+	return 0;
732
+}
733
+
734
+/**
735
+ * Issue HTTP block device read
736
+ *
737
+ * @v http		HTTP request
738
+ * @v block		Block data interface
739
+ * @v lba		Starting logical block address
740
+ * @v count		Number of blocks to transfer
741
+ * @v buffer		Data buffer
742
+ * @v len		Length of data buffer
743
+ * @ret rc		Return status code
744
+ */
745
+static int http_block_read ( struct http_request *http,
746
+			     struct interface *block,
747
+			     uint64_t lba, unsigned int count,
748
+			     userptr_t buffer, size_t len __unused ) {
749
+
750
+	return http_partial_read ( http, block, ( lba * HTTP_BLKSIZE ),
751
+				   buffer, ( count * HTTP_BLKSIZE ) );
752
+}
753
+
754
+/**
755
+ * Read HTTP block device capacity
756
+ *
757
+ * @v http		HTTP request
758
+ * @v block		Block data interface
759
+ * @ret rc		Return status code
760
+ */
761
+static int http_block_read_capacity ( struct http_request *http,
762
+				      struct interface *block ) {
763
+
764
+	return http_partial_read ( http, block, 0, 0, 0 );
765
+}
766
+
767
+/**
768
+ * Describe HTTP device in an ACPI table
769
+ *
770
+ * @v http		HTTP request
771
+ * @v acpi		ACPI table
772
+ * @v len		Length of ACPI table
773
+ * @ret rc		Return status code
774
+ */
775
+static int http_acpi_describe ( struct http_request *http,
776
+				struct acpi_description_header *acpi,
777
+				size_t len ) {
778
+
779
+	DBGC ( http, "HTTP %p cannot yet describe device in an ACPI table\n",
780
+	       http );
781
+	( void ) acpi;
782
+	( void ) len;
783
+	return 0;
784
+}
785
+
554 786
 /** HTTP socket interface operations */
555 787
 static struct interface_operation http_socket_operations[] = {
788
+	INTF_OP ( xfer_window, struct http_request *, http_socket_window ),
556 789
 	INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ),
557 790
 	INTF_OP ( xfer_window_changed, struct http_request *, http_step ),
558
-	INTF_OP ( intf_close, struct http_request *, http_done ),
791
+	INTF_OP ( intf_close, struct http_request *, http_close ),
559 792
 };
560 793
 
561 794
 /** HTTP socket interface descriptor */
@@ -563,9 +796,23 @@ static struct interface_descriptor http_socket_desc =
563 796
 	INTF_DESC_PASSTHRU ( struct http_request, socket,
564 797
 			     http_socket_operations, xfer );
565 798
 
799
+/** HTTP partial transfer interface operations */
800
+static struct interface_operation http_partial_operations[] = {
801
+	INTF_OP ( intf_close, struct http_request *, http_close ),
802
+};
803
+
804
+/** HTTP partial transfer interface descriptor */
805
+static struct interface_descriptor http_partial_desc =
806
+	INTF_DESC ( struct http_request, partial, http_partial_operations );
807
+
566 808
 /** HTTP data transfer interface operations */
567 809
 static struct interface_operation http_xfer_operations[] = {
568
-	INTF_OP ( intf_close, struct http_request *, http_done ),
810
+	INTF_OP ( xfer_window, struct http_request *, http_xfer_window ),
811
+	INTF_OP ( block_read, struct http_request *, http_block_read ),
812
+	INTF_OP ( block_read_capacity, struct http_request *,
813
+		  http_block_read_capacity ),
814
+	INTF_OP ( intf_close, struct http_request *, http_close ),
815
+	INTF_OP ( acpi_describe, struct http_request *, http_acpi_describe ),
569 816
 };
570 817
 
571 818
 /** HTTP data transfer interface descriptor */
@@ -605,9 +852,11 @@ int http_open_filter ( struct interface *xfer, struct uri *uri,
605 852
 		return -ENOMEM;
606 853
 	ref_init ( &http->refcnt, http_free );
607 854
 	intf_init ( &http->xfer, &http_xfer_desc, &http->refcnt );
855
+	intf_init ( &http->partial, &http_partial_desc, &http->refcnt );
608 856
        	http->uri = uri_get ( uri );
609 857
 	intf_init ( &http->socket, &http_socket_desc, &http->refcnt );
610 858
 	process_init ( &http->process, &http_process_desc, &http->refcnt );
859
+	http->flags = HTTP_TX_PENDING;
611 860
 
612 861
 	/* Open socket */
613 862
 	memset ( &server, 0, sizeof ( server ) );
@@ -630,7 +879,7 @@ int http_open_filter ( struct interface *xfer, struct uri *uri,
630 879
  err:
631 880
 	DBGC ( http, "HTTP %p could not create request: %s\n", 
632 881
 	       http, strerror ( rc ) );
633
-	http_done ( http, rc );
882
+	http_close ( http, rc );
634 883
 	ref_put ( &http->refcnt );
635 884
 	return rc;
636 885
 }

Loading…
취소
저장