|
@@ -42,6 +42,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
42
|
42
|
#include <ipxe/socket.h>
|
43
|
43
|
#include <ipxe/tcpip.h>
|
44
|
44
|
#include <ipxe/process.h>
|
|
45
|
+#include <ipxe/retry.h>
|
45
|
46
|
#include <ipxe/linebuf.h>
|
46
|
47
|
#include <ipxe/base64.h>
|
47
|
48
|
#include <ipxe/base16.h>
|
|
@@ -103,6 +104,8 @@ enum http_flags {
|
103
|
104
|
HTTP_BASIC_AUTH = 0x0020,
|
104
|
105
|
/** Provide Digest authentication details */
|
105
|
106
|
HTTP_DIGEST_AUTH = 0x0040,
|
|
107
|
+ /** Socket must be reopened */
|
|
108
|
+ HTTP_REOPEN_SOCKET = 0x0080,
|
106
|
109
|
};
|
107
|
110
|
|
108
|
111
|
/** HTTP receive state */
|
|
@@ -179,6 +182,9 @@ struct http_request {
|
179
|
182
|
char *auth_nonce;
|
180
|
183
|
/** Authentication opaque string (if any) */
|
181
|
184
|
char *auth_opaque;
|
|
185
|
+
|
|
186
|
+ /** Request retry timer */
|
|
187
|
+ struct retry_timer timer;
|
182
|
188
|
};
|
183
|
189
|
|
184
|
190
|
/**
|
|
@@ -249,13 +255,43 @@ static int http_socket_open ( struct http_request *http ) {
|
249
|
255
|
return 0;
|
250
|
256
|
}
|
251
|
257
|
|
|
258
|
+/**
|
|
259
|
+ * Retry HTTP request
|
|
260
|
+ *
|
|
261
|
+ * @v timer Retry timer
|
|
262
|
+ * @v fail Failure indicator
|
|
263
|
+ */
|
|
264
|
+static void http_retry ( struct retry_timer *timer, int fail __unused ) {
|
|
265
|
+ struct http_request *http =
|
|
266
|
+ container_of ( timer, struct http_request, timer );
|
|
267
|
+ int rc;
|
|
268
|
+
|
|
269
|
+ /* Reopen socket if required */
|
|
270
|
+ if ( http->flags & HTTP_REOPEN_SOCKET ) {
|
|
271
|
+ http->flags &= ~HTTP_REOPEN_SOCKET;
|
|
272
|
+ DBGC ( http, "HTTP %p reopening connection\n", http );
|
|
273
|
+ if ( ( rc = http_socket_open ( http ) ) != 0 ) {
|
|
274
|
+ http_close ( http, rc );
|
|
275
|
+ return;
|
|
276
|
+ }
|
|
277
|
+ }
|
|
278
|
+
|
|
279
|
+ /* Retry the request if applicable */
|
|
280
|
+ if ( http->flags & HTTP_TRY_AGAIN ) {
|
|
281
|
+ http->flags &= ~HTTP_TRY_AGAIN;
|
|
282
|
+ DBGC ( http, "HTTP %p retrying request\n", http );
|
|
283
|
+ http->flags |= HTTP_TX_PENDING;
|
|
284
|
+ http->rx_state = HTTP_RX_RESPONSE;
|
|
285
|
+ process_add ( &http->process );
|
|
286
|
+ }
|
|
287
|
+}
|
|
288
|
+
|
252
|
289
|
/**
|
253
|
290
|
* Mark HTTP request as completed successfully
|
254
|
291
|
*
|
255
|
292
|
* @v http HTTP request
|
256
|
293
|
*/
|
257
|
294
|
static void http_done ( struct http_request *http ) {
|
258
|
|
- int rc;
|
259
|
295
|
|
260
|
296
|
/* If we are not at an appropriate stage of the protocol
|
261
|
297
|
* (including being in the middle of a chunked transfer),
|
|
@@ -296,25 +332,17 @@ static void http_done ( struct http_request *http ) {
|
296
|
332
|
}
|
297
|
333
|
|
298
|
334
|
/* If the server is not intending to keep the connection
|
299
|
|
- * alive, then reopen the socket.
|
|
335
|
+ * alive, then close the socket and mark it as requiring
|
|
336
|
+ * reopening.
|
300
|
337
|
*/
|
301
|
338
|
if ( ! ( http->flags & HTTP_SERVER_KEEPALIVE ) ) {
|
302
|
|
- DBGC ( http, "HTTP %p reopening connection\n", http );
|
303
|
339
|
intf_restart ( &http->socket, 0 );
|
304
|
|
- if ( ( rc = http_socket_open ( http ) ) != 0 ) {
|
305
|
|
- http_close ( http, rc );
|
306
|
|
- return;
|
307
|
|
- }
|
|
340
|
+ http->flags &= ~HTTP_SERVER_KEEPALIVE;
|
|
341
|
+ http->flags |= HTTP_REOPEN_SOCKET;
|
308
|
342
|
}
|
309
|
|
- http->flags &= ~HTTP_SERVER_KEEPALIVE;
|
310
|
343
|
|
311
|
|
- /* Retry the request if applicable */
|
312
|
|
- if ( http->flags & HTTP_TRY_AGAIN ) {
|
313
|
|
- http->flags &= ~HTTP_TRY_AGAIN;
|
314
|
|
- http->flags |= HTTP_TX_PENDING;
|
315
|
|
- http->rx_state = HTTP_RX_RESPONSE;
|
316
|
|
- process_add ( &http->process );
|
317
|
|
- }
|
|
344
|
+ /* Start request retry timer */
|
|
345
|
+ start_timer_nodelay ( &http->timer );
|
318
|
346
|
}
|
319
|
347
|
|
320
|
348
|
/**
|
|
@@ -1467,6 +1495,7 @@ int http_open_filter ( struct interface *xfer, struct uri *uri,
|
1467
|
1495
|
http->filter = filter;
|
1468
|
1496
|
intf_init ( &http->socket, &http_socket_desc, &http->refcnt );
|
1469
|
1497
|
process_init ( &http->process, &http_process_desc, &http->refcnt );
|
|
1498
|
+ timer_init ( &http->timer, http_retry, &http->refcnt );
|
1470
|
1499
|
http->flags = HTTP_TX_PENDING;
|
1471
|
1500
|
|
1472
|
1501
|
/* Open socket */
|