瀏覽代碼

Update HTTP to use data-xfer interface.

tags/v0.9.3
Michael Brown 17 年之前
父節點
當前提交
735e07268e
共有 4 個文件被更改,包括 269 次插入285 次删除
  1. 13
    20
      src/core/linebuf.c
  2. 0
    46
      src/include/gpxe/http.h
  3. 2
    2
      src/include/gpxe/linebuf.h
  4. 254
    217
      src/net/tcp/http.c

+ 13
- 20
src/core/linebuf.c 查看文件

@@ -57,23 +57,20 @@ void empty_line_buffer ( struct line_buffer *linebuf ) {
57 57
  * @v linebuf			Line buffer
58 58
  * @v data			New data to add
59 59
  * @v len			Length of new data to add
60
- * @ret rc			Return status code
61
- * 
62
- * If line_buffer() returns >0, then an end of line has been reached
63
- * and the buffered-up line can be obtained from buffered_line().
64
- * Carriage returns and newlines will have been stripped, and the line
65
- * will be NUL-terminated.  This buffered line is valid only until the
66
- * next call to line_buffer() (or to empty_line_buffer()).
60
+ * @ret len			Consumed length, or negative error number
67 61
  *
68
- * @c data and @c len will be updated to reflect the data consumed by
69
- * line_buffer().
62
+ * After calling line_buffer(), use buffered_line() to determine
63
+ * whether or not a complete line is available.  Carriage returns and
64
+ * newlines will have been stripped, and the line will be
65
+ * NUL-terminated.  This buffered line is valid only until the next
66
+ * call to line_buffer() (or to empty_line_buffer()).
70 67
  *
71 68
  * Note that line buffers use dynamically allocated storage; you
72 69
  * should call empty_line_buffer() before freeing a @c struct @c
73 70
  * line_buffer.
74 71
  */
75
-int line_buffer ( struct line_buffer *linebuf,
76
-		  const char **data, size_t *len ) {
72
+ssize_t line_buffer ( struct line_buffer *linebuf,
73
+		      const char *data, size_t len ) {
77 74
 	const char *eol;
78 75
 	size_t consume;
79 76
 	size_t new_len;
@@ -84,10 +81,10 @@ int line_buffer ( struct line_buffer *linebuf,
84 81
 		empty_line_buffer ( linebuf );
85 82
 
86 83
 	/* Search for line terminator */
87
-	if ( ( eol = memchr ( *data, '\n', *len ) ) ) {
88
-		consume = ( eol - *data + 1 );
84
+	if ( ( eol = memchr ( data, '\n', len ) ) ) {
85
+		consume = ( eol - data + 1 );
89 86
 	} else {
90
-		consume = *len;
87
+		consume = len;
91 88
 	}
92 89
 
93 90
 	/* Reallocate data buffer and copy in new data */
@@ -95,15 +92,11 @@ int line_buffer ( struct line_buffer *linebuf,
95 92
 	new_data = realloc ( linebuf->data, ( new_len + 1 ) );
96 93
 	if ( ! new_data )
97 94
 		return -ENOMEM;
98
-	memcpy ( ( new_data + linebuf->len ), *data, consume );
95
+	memcpy ( ( new_data + linebuf->len ), data, consume );
99 96
 	new_data[new_len] = '\0';
100 97
 	linebuf->data = new_data;
101 98
 	linebuf->len = new_len;
102 99
 
103
-	/* Update data and len */
104
-	*data += consume;
105
-	*len -= consume;
106
-
107 100
 	/* If we have reached end of line, trim the line and mark as ready */
108 101
 	if ( eol ) {
109 102
 		linebuf->data[--linebuf->len] = '\0'; /* trim NL */
@@ -112,5 +105,5 @@ int line_buffer ( struct line_buffer *linebuf,
112 105
 		linebuf->ready = 1;
113 106
 	}
114 107
 
115
-	return 0;
108
+	return consume;
116 109
 }

+ 0
- 46
src/include/gpxe/http.h 查看文件

@@ -7,56 +7,10 @@
7 7
  *
8 8
  */
9 9
 
10
-#include <stdint.h>
11
-#include <gpxe/stream.h>
12
-#include <gpxe/async.h>
13
-#include <gpxe/linebuf.h>
14
-#include <gpxe/uri.h>
15
-
16 10
 /** HTTP default port */
17 11
 #define HTTP_PORT 80
18 12
 
19 13
 /** HTTPS default port */
20 14
 #define HTTPS_PORT 443
21 15
 
22
-/** HTTP receive state */
23
-enum http_rx_state {
24
-	HTTP_RX_RESPONSE = 0,
25
-	HTTP_RX_HEADER,
26
-	HTTP_RX_DATA,
27
-	HTTP_RX_DEAD,
28
-};
29
-
30
-/**
31
- * An HTTP request
32
- *
33
- */
34
-struct http_request {
35
-	/** URI being fetched */
36
-	struct uri *uri;
37
-	/** Data buffer to fill */
38
-	struct buffer *buffer;
39
-	/** Asynchronous operation */
40
-	struct async async;
41
-
42
-	/** HTTP response code */
43
-	unsigned int response;
44
-	/** HTTP Content-Length */
45
-	size_t content_length;
46
-
47
-	/** Server address */
48
-	struct sockaddr server;
49
-	/** Stream application for this request */
50
-	struct stream_application stream;
51
-	/** Number of bytes already sent */
52
-	size_t tx_offset;
53
-	/** RX state */
54
-	enum http_rx_state rx_state;
55
-	/** Line buffer for received header lines */
56
-	struct line_buffer linebuf;
57
-};
58
-
59
-extern int http_get ( struct uri *uri, struct buffer *buffer,
60
-		      struct async *parent );
61
-
62 16
 #endif /* _GPXE_HTTP_H */

+ 2
- 2
src/include/gpxe/linebuf.h 查看文件

@@ -21,8 +21,8 @@ struct line_buffer {
21 21
 };
22 22
 
23 23
 extern char * buffered_line ( struct line_buffer *linebuf );
24
-extern int line_buffer ( struct line_buffer *linebuf,
25
-			 const char **data, size_t *len );
24
+extern ssize_t line_buffer ( struct line_buffer *linebuf,
25
+			     const char *data, size_t len );
26 26
 extern void empty_line_buffer ( struct line_buffer *linebuf );
27 27
 
28 28
 #endif /* _GPXE_LINEBUF_H */

+ 254
- 217
src/net/tcp/http.c 查看文件

@@ -23,7 +23,7 @@
23 23
  *
24 24
  */
25 25
 
26
-#include <stddef.h>
26
+#include <stdint.h>
27 27
 #include <stdlib.h>
28 28
 #include <stdio.h>
29 29
 #include <string.h>
@@ -31,52 +31,99 @@
31 31
 #include <byteswap.h>
32 32
 #include <errno.h>
33 33
 #include <assert.h>
34
-#include <gpxe/async.h>
35 34
 #include <gpxe/uri.h>
36
-#include <gpxe/buffer.h>
37
-#include <gpxe/download.h>
38
-#include <gpxe/resolv.h>
39
-#include <gpxe/tcp.h>
35
+#include <gpxe/refcnt.h>
36
+#include <gpxe/iobuf.h>
37
+#include <gpxe/xfer.h>
38
+#include <gpxe/open.h>
39
+#include <gpxe/socket.h>
40
+#include <gpxe/tcpip.h>
41
+#include <gpxe/process.h>
42
+#include <gpxe/linebuf.h>
40 43
 #include <gpxe/tls.h>
41 44
 #include <gpxe/http.h>
42 45
 
43
-static struct async_operations http_async_operations;
46
+/** HTTP receive state */
47
+enum http_rx_state {
48
+	HTTP_RX_RESPONSE = 0,
49
+	HTTP_RX_HEADER,
50
+	HTTP_RX_DATA,
51
+	HTTP_RX_DEAD,
52
+};
44 53
 
45
-static inline struct http_request *
46
-stream_to_http ( struct stream_application *app ) {
47
-	return container_of ( app, struct http_request, stream );
48
-}
54
+/**
55
+ * An HTTP request
56
+ *
57
+ */
58
+struct http_request {
59
+	/** Reference count */
60
+	struct refcnt refcnt;
61
+	/** Data transfer interface */
62
+	struct xfer_interface xfer;
63
+
64
+	/** URI being fetched */
65
+	struct uri *uri;
66
+	/** Transport layer interface */
67
+	struct xfer_interface socket;
68
+
69
+	/** TX process */
70
+	struct process process;
71
+
72
+	/** HTTP response code */
73
+	unsigned int response;
74
+	/** HTTP Content-Length */
75
+	size_t content_length;
76
+	/** Received length */
77
+	size_t rx_len;
78
+	/** RX state */
79
+	enum http_rx_state rx_state;
80
+	/** Line buffer for received header lines */
81
+	struct line_buffer linebuf;
82
+};
83
+
84
+/**
85
+ * Free HTTP request
86
+ *
87
+ * @v refcnt		Reference counter
88
+ */
89
+static void http_free ( struct refcnt *refcnt ) {
90
+	struct http_request *http =
91
+		container_of ( refcnt, struct http_request, refcnt );
92
+
93
+	uri_put ( http->uri );
94
+	empty_line_buffer ( &http->linebuf );
95
+	free ( http );
96
+};
49 97
 
50 98
 /**
51 99
  * Mark HTTP request as complete
52 100
  *
53 101
  * @v http		HTTP request
54 102
  * @v rc		Return status code
55
- *
56 103
  */
57 104
 static void http_done ( struct http_request *http, int rc ) {
58 105
 
59
-	/* Close stream connection */
60
-	stream_close ( &http->stream );
61
-
62 106
 	/* Prevent further processing of any current packet */
63 107
 	http->rx_state = HTTP_RX_DEAD;
64 108
 
65
-	/* Free up any dynamically allocated storage */
66
-	empty_line_buffer ( &http->linebuf );
67
-
68 109
 	/* If we had a Content-Length, and the received content length
69 110
 	 * isn't correct, flag an error
70 111
 	 */
71 112
 	if ( http->content_length &&
72
-	     ( http->content_length != http->buffer->fill ) ) {
113
+	     ( http->content_length != http->rx_len ) ) {
73 114
 		DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n",
74
-		       http, http->buffer->fill, http->content_length );
115
+		       http, http->rx_len, http->content_length );
75 116
 		rc = -EIO;
76 117
 	}
77 118
 
78
-	/* Mark async operation as complete */
79
-	async_done ( &http->async, rc );
119
+	/* Remove process */
120
+	process_del ( &http->process );
121
+
122
+	/* Close all data transfer interfaces */
123
+	xfer_nullify ( &http->socket );
124
+	xfer_close ( &http->socket, rc );
125
+	xfer_nullify ( &http->xfer );
126
+	xfer_close ( &http->xfer, rc );
80 127
 }
81 128
 
82 129
 /**
@@ -103,33 +150,29 @@ static int http_response_to_rc ( unsigned int response ) {
103 150
  *
104 151
  * @v http		HTTP request
105 152
  * @v response		HTTP response
153
+ * @ret rc		Return status code
106 154
  */
107
-static void http_rx_response ( struct http_request *http, char *response ) {
155
+static int http_rx_response ( struct http_request *http, char *response ) {
108 156
 	char *spc;
109
-	int rc = -EIO;
157
+	int rc;
110 158
 
111 159
 	DBGC ( http, "HTTP %p response \"%s\"\n", http, response );
112 160
 
113 161
 	/* Check response starts with "HTTP/" */
114 162
 	if ( strncmp ( response, "HTTP/", 5 ) != 0 )
115
-		goto err;
163
+		return -EIO;
116 164
 
117 165
 	/* Locate and check response code */
118 166
 	spc = strchr ( response, ' ' );
119 167
 	if ( ! spc )
120
-		goto err;
168
+		return -EIO;
121 169
 	http->response = strtoul ( spc, NULL, 10 );
122 170
 	if ( ( rc = http_response_to_rc ( http->response ) ) != 0 )
123
-		goto err;
171
+		return rc;
124 172
 
125 173
 	/* Move to received headers */
126 174
 	http->rx_state = HTTP_RX_HEADER;
127
-	return;
128
-
129
- err:
130
-	DBGC ( http, "HTTP %p bad response\n", http );
131
-	http_done ( http, rc );
132
-	return;
175
+	return 0;
133 176
 }
134 177
 
135 178
 /**
@@ -142,7 +185,6 @@ static void http_rx_response ( struct http_request *http, char *response ) {
142 185
 static int http_rx_content_length ( struct http_request *http,
143 186
 				    const char *value ) {
144 187
 	char *endp;
145
-	int rc;
146 188
 
147 189
 	http->content_length = strtoul ( value, &endp, 10 );
148 190
 	if ( *endp != '\0' ) {
@@ -151,22 +193,14 @@ static int http_rx_content_length ( struct http_request *http,
151 193
 		return -EIO;
152 194
 	}
153 195
 
154
-	/* Try to presize the receive buffer */
155
-	if ( ( rc = expand_buffer ( http->buffer,
156
-				    http->content_length ) ) != 0 ) {
157
-		/* May as well abandon the download now; it will fail */
158
-		DBGC ( http, "HTTP %p could not presize buffer: %s\n",
159
-		       http, strerror ( rc ) );
160
-		return rc;
161
-	}
196
+	/* Use seek() to notify recipient of filesize */
197
+	xfer_seek ( &http->xfer, http->content_length, SEEK_SET );
198
+	xfer_seek ( &http->xfer, 0, SEEK_SET );
162 199
 
163 200
 	return 0;
164 201
 }
165 202
 
166
-/**
167
- * An HTTP header handler
168
- *
169
- */
203
+/** An HTTP header handler */
170 204
 struct http_header_handler {
171 205
 	/** Name (e.g. "Content-Length") */
172 206
 	const char *header;
@@ -195,27 +229,30 @@ struct http_header_handler http_header_handlers[] = {
195 229
  *
196 230
  * @v http		HTTP request
197 231
  * @v header		HTTP header
232
+ * @ret rc		Return status code
198 233
  */
199
-static void http_rx_header ( struct http_request *http, char *header ) {
234
+static int http_rx_header ( struct http_request *http, char *header ) {
200 235
 	struct http_header_handler *handler;
201 236
 	char *separator;
202 237
 	char *value;
203
-	int rc = -EIO;
238
+	int rc;
204 239
 
205 240
 	/* An empty header line marks the transition to the data phase */
206 241
 	if ( ! header[0] ) {
207 242
 		DBGC ( http, "HTTP %p start of data\n", http );
208 243
 		empty_line_buffer ( &http->linebuf );
209 244
 		http->rx_state = HTTP_RX_DATA;
210
-		return;
245
+		return 0;
211 246
 	}
212 247
 
213 248
 	DBGC ( http, "HTTP %p header \"%s\"\n", http, header );
214 249
 
215 250
 	/* Split header at the ": " */
216 251
 	separator = strstr ( header, ": " );
217
-	if ( ! separator )
218
-		goto err;
252
+	if ( ! separator ) {
253
+		DBGC ( http, "HTTP %p malformed header\n", http );
254
+		return -EIO;
255
+	}
219 256
 	*separator = '\0';
220 257
 	value = ( separator + 2 );
221 258
 
@@ -223,265 +260,265 @@ static void http_rx_header ( struct http_request *http, char *header ) {
223 260
 	for ( handler = http_header_handlers ; handler->header ; handler++ ) {
224 261
 		if ( strcasecmp ( header, handler->header ) == 0 ) {
225 262
 			if ( ( rc = handler->rx ( http, value ) ) != 0 )
226
-				goto err;
263
+				return rc;
227 264
 			break;
228 265
 		}
229 266
 	}
230
-	return;
231
-
232
- err:
233
-	DBGC ( http, "HTTP %p bad header\n", http );
234
-	http_done ( http, rc );
235
-	return;
267
+	return 0;
236 268
 }
237 269
 
270
+/** An HTTP line-based data handler */
271
+struct http_line_handler {
272
+	/** Handle line
273
+	 *
274
+	 * @v http	HTTP request
275
+	 * @v line	Line to handle
276
+	 * @ret rc	Return status code
277
+	 */
278
+	int ( * rx ) ( struct http_request *http, char *line );
279
+};
280
+
281
+/** List of HTTP line-based data handlers */
282
+struct http_line_handler http_line_handlers[] = {
283
+	[HTTP_RX_RESPONSE]	= { .rx = http_rx_response },
284
+	[HTTP_RX_HEADER]	= { .rx = http_rx_header },
285
+};
286
+
238 287
 /**
239 288
  * Handle new data arriving via HTTP connection in the data phase
240 289
  *
241 290
  * @v http		HTTP request
242
- * @v data		New data
243
- * @v len		Length of new data
291
+ * @v iobuf		I/O buffer
292
+ * @ret rc		Return status code
244 293
  */
245
-static void http_rx_data ( struct http_request *http,
246
-			   const char *data, size_t len ) {
294
+static int http_rx_data ( struct http_request *http,
295
+			  struct io_buffer *iobuf ) {
247 296
 	int rc;
248 297
 
249
-	/* Fill data buffer */
250
-	if ( ( rc = fill_buffer ( http->buffer, data,
251
-				  http->buffer->fill, len ) ) != 0 ) {
252
-		DBGC ( http, "HTTP %p failed to fill data buffer: %s\n",
253
-		       http, strerror ( rc ) );
254
-		http_done ( http, rc );
255
-		return;
256
-	}
298
+	/* Update received length */
299
+	http->rx_len += iob_len ( iobuf );
257 300
 
258
-	/* Update progress */
259
-	http->async.completed = http->buffer->fill;
260
-	http->async.total = http->content_length;
301
+	/* Hand off data buffer */
302
+	if ( ( rc = xfer_deliver_iob ( &http->xfer, iobuf ) ) != 0 )
303
+		return rc;
261 304
 
262 305
 	/* If we have reached the content-length, stop now */
263 306
 	if ( http->content_length &&
264
-	     ( http->buffer->fill >= http->content_length ) ) {
307
+	     ( http->rx_len >= http->content_length ) ) {
265 308
 		http_done ( http, 0 );
266 309
 	}
310
+
311
+	return 0;
267 312
 }
268 313
 
269 314
 /**
270 315
  * Handle new data arriving via HTTP connection
271 316
  *
272
- * @v http		HTTP request
273
- * @v data		New data
274
- * @v len		Length of new data
317
+ * @v socket		Transport layer interface
318
+ * @v iobuf		I/O buffer
319
+ * @ret rc		Return status code
275 320
  */
276
-static void http_newdata ( struct stream_application *app,
277
-			   void *data, size_t len ) {
278
-	struct http_request *http = stream_to_http ( app );
279
-	const char *buf = data;
321
+static int http_socket_deliver_iob ( struct xfer_interface *socket,
322
+				     struct io_buffer *iobuf ) {
323
+	struct http_request *http =
324
+		container_of ( socket, struct http_request, socket );
325
+	struct http_line_handler *lh;
280 326
 	char *line;
281
-	int rc;
327
+	ssize_t len;
328
+	int rc = 0;
282 329
 
283
-	while ( len ) {
284
-		if ( http->rx_state == HTTP_RX_DEAD ) {
330
+	while ( iob_len ( iobuf ) ) {
331
+		switch ( http->rx_state ) {
332
+		case HTTP_RX_DEAD:
285 333
 			/* Do no further processing */
286
-			return;
287
-		} else if ( http->rx_state == HTTP_RX_DATA ) {
334
+			goto done;
335
+		case HTTP_RX_DATA:
288 336
 			/* Once we're into the data phase, just fill
289 337
 			 * the data buffer
290 338
 			 */
291
-			http_rx_data ( http, buf, len );
292
-			return;
293
-		} else {
339
+			rc = http_rx_data ( http, iobuf );
340
+			iobuf = NULL;
341
+			goto done;
342
+		case HTTP_RX_RESPONSE:
343
+		case HTTP_RX_HEADER:
294 344
 			/* In the other phases, buffer and process a
295 345
 			 * line at a time
296 346
 			 */
297
-			if ( ( rc = line_buffer ( &http->linebuf, &buf,
298
-						  &len ) ) != 0 ) {
347
+			len = line_buffer ( &http->linebuf, iobuf->data,
348
+					    iob_len ( iobuf ) );
349
+			if ( len < 0 ) {
299 350
 				DBGC ( http, "HTTP %p could not buffer line: "
300 351
 				       "%s\n", http, strerror ( rc ) );
301
-				http_done ( http, rc );
302
-				return;
352
+				goto done;
303 353
 			}
304
-			if ( ( line = buffered_line ( &http->linebuf ) ) ) {
305
-				switch ( http->rx_state ) {
306
-				case HTTP_RX_RESPONSE:
307
-					http_rx_response ( http, line );
308
-					break;
309
-				case HTTP_RX_HEADER:
310
-					http_rx_header ( http, line );
311
-					break;
312
-				default:
313
-					assert ( 0 );
314
-					break;
315
-				}
354
+			iob_pull ( iobuf, len );
355
+			line = buffered_line ( &http->linebuf );
356
+			if ( line ) {
357
+				lh = &http_line_handlers[http->rx_state];
358
+				if ( ( rc = lh->rx ( http, line ) ) != 0 )
359
+					goto done;
316 360
 			}
361
+			break;
362
+		default:
363
+			assert ( 0 );
364
+			break;
317 365
 		}
318 366
 	}
367
+
368
+ done:
369
+	if ( rc )
370
+		http_done ( http, rc );
371
+	free_iob ( iobuf );
372
+	return rc;
319 373
 }
320 374
 
321 375
 /**
322
- * Send HTTP data
376
+ * HTTP process
323 377
  *
324
- * @v app		Stream application
325
- * @v buf		Temporary data buffer
326
- * @v len		Length of temporary data buffer
378
+ * @v process		Process
327 379
  */
328
-static void http_senddata ( struct stream_application *app,
329
-			    void *buf, size_t len ) {
330
-	struct http_request *http = stream_to_http ( app );
380
+static void http_step ( struct process *process ) {
381
+	struct http_request *http =
382
+		container_of ( process, struct http_request, process );
331 383
 	const char *path = http->uri->path;
332 384
 	const char *host = http->uri->host;
333 385
 	const char *query = http->uri->query;
386
+	int rc;
334 387
 
335
-	len = snprintf ( buf, len,
336
-			 "GET %s%s%s HTTP/1.1\r\n"
337
-			 "User-Agent: gPXE/" VERSION "\r\n"
338
-			 "Host: %s\r\n"
339
-			 "\r\n",
340
-			 ( path ? path : "/" ),
341
-			 ( query ? "?" : "" ),
342
-			 ( query ? query : "" ),
343
-			 host );
344
-
345
-	stream_send ( app, ( buf + http->tx_offset ),
346
-		      ( len - http->tx_offset ) );
388
+	if ( xfer_ready ( &http->socket ) == 0 ) {
389
+		process_del ( &http->process );
390
+		if ( ( rc = xfer_printf ( &http->socket,
391
+					  "GET %s%s%s HTTP/1.1\r\n"
392
+					  "User-Agent: gPXE/" VERSION "\r\n"
393
+					  "Host: %s\r\n"
394
+					  "\r\n",
395
+					  ( path ? path : "/" ),
396
+					  ( query ? "?" : "" ),
397
+					  ( query ? query : "" ),
398
+					  host ) ) != 0 ) {
399
+			http_done ( http, rc );
400
+		}
401
+	}
347 402
 }
348 403
 
349 404
 /**
350
- * HTTP data acknowledged
405
+ * HTTP connection closed by network stack
351 406
  *
352
- * @v app		Stream application
353
- * @v len		Length of acknowledged data
407
+ * @v socket		Transport layer interface
408
+ * @v rc		Reason for close
354 409
  */
355
-static void http_acked ( struct stream_application *app, size_t len ) {
356
-	struct http_request *http = stream_to_http ( app );
410
+static void http_socket_close ( struct xfer_interface *socket, int rc ) {
411
+	struct http_request *http =
412
+		container_of ( socket, struct http_request, socket );
357 413
 
358
-	http->tx_offset += len;
414
+	DBGC ( http, "HTTP %p socket closed: %s\n",
415
+	       http, strerror ( rc ) );
416
+	
417
+	http_done ( http, rc );
359 418
 }
360 419
 
420
+/** HTTP socket operations */
421
+static struct xfer_interface_operations http_socket_operations = {
422
+	.close		= http_socket_close,
423
+	.vredirect	= xfer_vopen,
424
+	.request	= ignore_xfer_request,
425
+	.seek		= ignore_xfer_seek,
426
+	.alloc_iob	= default_xfer_alloc_iob,
427
+	.deliver_iob	= http_socket_deliver_iob,
428
+	.deliver_raw	= xfer_deliver_as_iob,
429
+};
430
+
361 431
 /**
362
- * HTTP connection closed by network stack
432
+ * Close HTTP data transfer interface
363 433
  *
364
- * @v app		Stream application
434
+ * @v xfer		Data transfer interface
435
+ * @v rc		Reason for close
365 436
  */
366
-static void http_closed ( struct stream_application *app, int rc ) {
367
-	struct http_request *http = stream_to_http ( app );
437
+static void http_xfer_close ( struct xfer_interface *xfer, int rc ) {
438
+	struct http_request *http =
439
+		container_of ( xfer, struct http_request, xfer );
368 440
 
369
-	DBGC ( http, "HTTP %p connection closed: %s\n",
441
+	DBGC ( http, "HTTP %p interface closed: %s\n",
370 442
 	       http, strerror ( rc ) );
371
-	
443
+
372 444
 	http_done ( http, rc );
373 445
 }
374 446
 
375
-/** HTTP stream operations */
376
-static struct stream_application_operations http_stream_operations = {
377
-	.closed		= http_closed,
378
-	.acked		= http_acked,
379
-	.newdata	= http_newdata,
380
-	.senddata	= http_senddata,
447
+/** HTTP data transfer interface operations */
448
+static struct xfer_interface_operations http_xfer_operations = {
449
+	.close		= http_xfer_close,
450
+	.vredirect	= ignore_xfer_vredirect,
451
+	.request	= ignore_xfer_request,
452
+	.seek		= ignore_xfer_seek,
453
+	.alloc_iob	= default_xfer_alloc_iob,
454
+	.deliver_iob	= xfer_deliver_as_raw,
455
+	.deliver_raw	= ignore_xfer_deliver_raw,
381 456
 };
382 457
 
383 458
 /**
384
- * Initiate a HTTP connection
459
+ * Initiate an HTTP connection
385 460
  *
461
+ * @v xfer		Data transfer interface
386 462
  * @v uri		Uniform Resource Identifier
387
- * @v buffer		Buffer into which to download file
388
- * @v parent		Parent asynchronous operation
389 463
  * @ret rc		Return status code
390 464
  */
391
-int http_get ( struct uri *uri, struct buffer *buffer, struct async *parent ) {
392
-	struct http_request *http = NULL;
393
-	struct sockaddr_tcpip *st;
465
+int http_open ( struct xfer_interface *xfer, struct uri *uri ) {
466
+	struct http_request *http;
467
+	struct sockaddr_tcpip server;
394 468
 	int rc;
395 469
 
470
+	/* Sanity checks */
471
+	if ( ! uri->host )
472
+		return -EINVAL;
473
+
396 474
 	/* Allocate and populate HTTP structure */
397 475
 	http = malloc ( sizeof ( *http ) );
398 476
 	if ( ! http )
399 477
 		return -ENOMEM;
400 478
 	memset ( http, 0, sizeof ( *http ) );
401
-	http->uri = uri;
402
-	http->buffer = buffer;
403
-	async_init ( &http->async, &http_async_operations, parent );
404
-	http->stream.op = &http_stream_operations;
405
-	st = ( struct sockaddr_tcpip * ) &http->server;
406
-	st->st_port = htons ( uri_port ( http->uri, HTTP_PORT ) );
407
-
408
-	/* Open TCP connection */
409
-	if ( ( rc = tcp_open ( &http->stream ) ) != 0 )
479
+	http->refcnt.free = http_free;
480
+	xfer_init ( &http->xfer, &http_xfer_operations, &http->refcnt );
481
+       	http->uri = uri_get ( uri );
482
+	xfer_init ( &http->socket, &http_socket_operations, &http->refcnt );
483
+	process_init ( &http->process, http_step, &http->refcnt );
484
+
485
+	/* Open socket */
486
+	memset ( &server, 0, sizeof ( server ) );
487
+	server.st_port = htons ( uri_port ( http->uri, HTTP_PORT ) );
488
+	if ( ( rc = xfer_open_named_socket ( &http->socket, SOCK_STREAM,
489
+					     ( struct sockaddr * ) &server,
490
+					     uri->host, NULL ) ) != 0 )
410 491
 		goto err;
492
+
493
+#if 0
411 494
 	if ( strcmp ( http->uri->scheme, "https" ) == 0 ) {
412 495
 		st->st_port = htons ( uri_port ( http->uri, HTTPS_PORT ) );
413 496
 		if ( ( rc = add_tls ( &http->stream ) ) != 0 )
414 497
 			goto err;
415 498
 	}
499
+#endif
416 500
 
417
-	/* Start name resolution.  The download proper will start when
418
-	 * name resolution completes.
419
-	 */
420
-	if ( ( rc = resolv ( uri->host, &http->server, &http->async ) ) != 0 )
421
-		goto err;
422
-
501
+	/* Attach to parent interface, mortalise self, and return */
502
+	xfer_plug_plug ( &http->xfer, xfer );
503
+	ref_put ( &http->refcnt );
423 504
 	return 0;
424 505
 
425 506
  err:
426 507
 	DBGC ( http, "HTTP %p could not create request: %s\n", 
427 508
 	       http, strerror ( rc ) );
428
-	async_uninit ( &http->async );
429
-	free ( http );
509
+	http_done ( http, rc );
510
+	ref_put ( &http->refcnt );
430 511
 	return rc;
431 512
 }
432 513
 
433
-/**
434
- * Handle name resolution completion
435
- *
436
- * @v async		HTTP asynchronous operation
437
- * @v signal		SIGCHLD
438
- */
439
-static void http_sigchld ( struct async *async, enum signal signal __unused ) {
440
-	struct http_request *http =
441
-		container_of ( async, struct http_request, async );
442
-	int rc;
443
-
444
-	/* If name resolution failed, abort now */
445
-	async_wait ( async, &rc, 1 );
446
-	if ( rc != 0 ) {
447
-		http_done ( http, rc );
448
-		return;
449
-	}
450
-
451
-	/* Otherwise, start the HTTP connection */
452
-	if ( ( rc = stream_connect ( &http->stream, &http->server ) ) != 0 ) {
453
-		DBGC ( http, "HTTP %p could not connect stream: %s\n",
454
-		       http, strerror ( rc ) );
455
-		http_done ( http, rc );
456
-		return;
457
-	}
458
-}
459
-
460
-/**
461
- * Free HTTP connection
462
- *
463
- * @v async		Asynchronous operation
464
- */
465
-static void http_reap ( struct async *async ) {
466
-	free ( container_of ( async, struct http_request, async ) );
467
-}
468
-
469
-/** HTTP asynchronous operations */
470
-static struct async_operations http_async_operations = {
471
-	.reap = http_reap,
472
-	.signal = {
473
-		[SIGCHLD] = http_sigchld,
474
-	},
475
-};
476
-
477
-/** HTTP download protocol */
478
-struct download_protocol http_download_protocol __download_protocol = {
479
-	.name = "http",
480
-	.start_download = http_get,
514
+/** HTTP URI opener */
515
+struct uri_opener http_uri_opener __uri_opener = {
516
+	.scheme	= "http",
517
+	.open	= http_open,
481 518
 };
482 519
 
483
-/** HTTPS download protocol */
484
-struct download_protocol https_download_protocol __download_protocol = {
485
-	.name = "https",
486
-	.start_download = http_get,
520
+/** HTTPS URI opener */
521
+struct uri_opener https_uri_opener __uri_opener = {
522
+	.scheme	= "https",
523
+	.open	= http_open,
487 524
 };

Loading…
取消
儲存