Browse Source

[http] Use a retry timer to trigger retried requests

Use a retry timer to allow for the possibility of deferring a retried
request.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
0d657b8e94
1 changed files with 44 additions and 15 deletions
  1. 44
    15
      src/net/tcp/httpcore.c

+ 44
- 15
src/net/tcp/httpcore.c View File

42
 #include <ipxe/socket.h>
42
 #include <ipxe/socket.h>
43
 #include <ipxe/tcpip.h>
43
 #include <ipxe/tcpip.h>
44
 #include <ipxe/process.h>
44
 #include <ipxe/process.h>
45
+#include <ipxe/retry.h>
45
 #include <ipxe/linebuf.h>
46
 #include <ipxe/linebuf.h>
46
 #include <ipxe/base64.h>
47
 #include <ipxe/base64.h>
47
 #include <ipxe/base16.h>
48
 #include <ipxe/base16.h>
103
 	HTTP_BASIC_AUTH = 0x0020,
104
 	HTTP_BASIC_AUTH = 0x0020,
104
 	/** Provide Digest authentication details */
105
 	/** Provide Digest authentication details */
105
 	HTTP_DIGEST_AUTH = 0x0040,
106
 	HTTP_DIGEST_AUTH = 0x0040,
107
+	/** Socket must be reopened */
108
+	HTTP_REOPEN_SOCKET = 0x0080,
106
 };
109
 };
107
 
110
 
108
 /** HTTP receive state */
111
 /** HTTP receive state */
179
 	char *auth_nonce;
182
 	char *auth_nonce;
180
 	/** Authentication opaque string (if any) */
183
 	/** Authentication opaque string (if any) */
181
 	char *auth_opaque;
184
 	char *auth_opaque;
185
+
186
+	/** Request retry timer */
187
+	struct retry_timer timer;
182
 };
188
 };
183
 
189
 
184
 /**
190
 /**
249
 	return 0;
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
  * Mark HTTP request as completed successfully
290
  * Mark HTTP request as completed successfully
254
  *
291
  *
255
  * @v http		HTTP request
292
  * @v http		HTTP request
256
  */
293
  */
257
 static void http_done ( struct http_request *http ) {
294
 static void http_done ( struct http_request *http ) {
258
-	int rc;
259
 
295
 
260
 	/* If we are not at an appropriate stage of the protocol
296
 	/* If we are not at an appropriate stage of the protocol
261
 	 * (including being in the middle of a chunked transfer),
297
 	 * (including being in the middle of a chunked transfer),
296
 	}
332
 	}
297
 
333
 
298
 	/* If the server is not intending to keep the connection
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
 	if ( ! ( http->flags & HTTP_SERVER_KEEPALIVE ) ) {
338
 	if ( ! ( http->flags & HTTP_SERVER_KEEPALIVE ) ) {
302
-		DBGC ( http, "HTTP %p reopening connection\n", http );
303
 		intf_restart ( &http->socket, 0 );
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
 	http->filter = filter;
1495
 	http->filter = filter;
1468
 	intf_init ( &http->socket, &http_socket_desc, &http->refcnt );
1496
 	intf_init ( &http->socket, &http_socket_desc, &http->refcnt );
1469
 	process_init ( &http->process, &http_process_desc, &http->refcnt );
1497
 	process_init ( &http->process, &http_process_desc, &http->refcnt );
1498
+	timer_init ( &http->timer, http_retry, &http->refcnt );
1470
 	http->flags = HTTP_TX_PENDING;
1499
 	http->flags = HTTP_TX_PENDING;
1471
 
1500
 
1472
 	/* Open socket */
1501
 	/* Open socket */

Loading…
Cancel
Save