Browse Source

[http] Eliminate polling while waiting for window to open

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
3ad1a1a60a
1 changed files with 46 additions and 32 deletions
  1. 46
    32
      src/net/tcp/http.c

+ 46
- 32
src/net/tcp/http.c View File

48
 
48
 
49
 FEATURE ( FEATURE_PROTOCOL, "HTTP", DHCP_EB_FEATURE_HTTP, 1 );
49
 FEATURE ( FEATURE_PROTOCOL, "HTTP", DHCP_EB_FEATURE_HTTP, 1 );
50
 
50
 
51
+/** HTTP transmission state */
52
+enum http_tx_state {
53
+	HTTP_TX_REQUEST = 0,
54
+	HTTP_TX_DONE,
55
+};
56
+
51
 /** HTTP receive state */
57
 /** HTTP receive state */
52
 enum http_rx_state {
58
 enum http_rx_state {
53
 	HTTP_RX_RESPONSE = 0,
59
 	HTTP_RX_RESPONSE = 0,
75
 
81
 
76
 	/** TX process */
82
 	/** TX process */
77
 	struct process process;
83
 	struct process process;
84
+	/** TX state */
85
+	enum http_tx_state tx_state;
78
 
86
 
79
 	/** HTTP response code */
87
 	/** HTTP response code */
80
 	unsigned int response;
88
 	unsigned int response;
498
 	int rc;
506
 	int rc;
499
 	int request_len = unparse_uri ( NULL, 0, http->uri,
507
 	int request_len = unparse_uri ( NULL, 0, http->uri,
500
 					URI_PATH_BIT | URI_QUERY_BIT );
508
 					URI_PATH_BIT | URI_QUERY_BIT );
509
+	char request[ request_len + 1 /* NUL */ ];
501
 
510
 
502
-	if ( xfer_window ( &http->socket ) ) {
503
-		char request[request_len + 1];
511
+	/* Do nothing if we have already transmitted the request */
512
+	if ( http->tx_state != HTTP_TX_REQUEST )
513
+		return;
504
 
514
 
505
-		/* Construct path?query request */
506
-		unparse_uri ( request, sizeof ( request ), http->uri,
507
-			      URI_PATH_BIT | URI_QUERY_BIT );
515
+	/* Do nothing until socket is ready */
516
+	if ( ! xfer_window ( &http->socket ) )
517
+		return;
508
 
518
 
509
-		/* We want to execute only once */
510
-		process_del ( &http->process );
519
+	/* Construct path?query request */
520
+	unparse_uri ( request, sizeof ( request ), http->uri,
521
+		      URI_PATH_BIT | URI_QUERY_BIT );
511
 
522
 
512
-		/* Construct authorisation, if applicable */
513
-		if ( user ) {
514
-			/* Make "user:password" string from decoded fields */
515
-			snprintf ( ( ( char * ) user_pw ), sizeof ( user_pw ),
516
-				   "%s:%s", user, password );
523
+	/* Construct authorisation, if applicable */
524
+	if ( user ) {
525
+		/* Make "user:password" string from decoded fields */
526
+		snprintf ( ( ( char * ) user_pw ), sizeof ( user_pw ),
527
+			   "%s:%s", user, password );
517
 
528
 
518
-			/* Base64-encode the "user:password" string */
519
-			base64_encode ( user_pw, user_pw_len, user_pw_base64 );
520
-		}
529
+		/* Base64-encode the "user:password" string */
530
+		base64_encode ( user_pw, user_pw_len, user_pw_base64 );
531
+	}
521
 
532
 
522
-		/* Send GET request */
523
-		if ( ( rc = xfer_printf ( &http->socket,
524
-					  "GET %s%s HTTP/1.1\r\n"
525
-					  "User-Agent: iPXE/" VERSION "\r\n"
526
-					  "%s%s%s"
527
-					  "Host: %s\r\n"
528
-					  "\r\n",
529
-					  http->uri->path ? "" : "/",
530
-					  request,
531
-					  ( user ?
532
-					    "Authorization: Basic " : "" ),
533
-					  ( user ? user_pw_base64 : "" ),
534
-					  ( user ? "\r\n" : "" ),
535
-					  host ) ) != 0 ) {
536
-			http_done ( http, rc );
537
-		}
533
+	/* Mark request as transmitted */
534
+	http->tx_state = HTTP_TX_DONE;
535
+
536
+	/* Send GET request */
537
+	if ( ( rc = xfer_printf ( &http->socket,
538
+				  "GET %s%s HTTP/1.1\r\n"
539
+				  "User-Agent: iPXE/" VERSION "\r\n"
540
+				  "%s%s%s"
541
+				  "Host: %s\r\n"
542
+				  "\r\n",
543
+				  http->uri->path ? "" : "/",
544
+				  request,
545
+				  ( user ?
546
+				    "Authorization: Basic " : "" ),
547
+				  ( user ? user_pw_base64 : "" ),
548
+				  ( user ? "\r\n" : "" ),
549
+				  host ) ) != 0 ) {
550
+		http_done ( http, rc );
538
 	}
551
 	}
539
 }
552
 }
540
 
553
 
541
 /** HTTP socket interface operations */
554
 /** HTTP socket interface operations */
542
 static struct interface_operation http_socket_operations[] = {
555
 static struct interface_operation http_socket_operations[] = {
543
 	INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ),
556
 	INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ),
557
+	INTF_OP ( xfer_window_changed, struct http_request *, http_step ),
544
 	INTF_OP ( intf_close, struct http_request *, http_done ),
558
 	INTF_OP ( intf_close, struct http_request *, http_done ),
545
 };
559
 };
546
 
560
 
561
 
575
 
562
 /** HTTP process descriptor */
576
 /** HTTP process descriptor */
563
 static struct process_descriptor http_process_desc =
577
 static struct process_descriptor http_process_desc =
564
-	PROC_DESC ( struct http_request, process, http_step );
578
+	PROC_DESC_ONCE ( struct http_request, process, http_step );
565
 
579
 
566
 /**
580
 /**
567
  * Initiate an HTTP connection, with optional filter
581
  * Initiate an HTTP connection, with optional filter

Loading…
Cancel
Save