]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[http] Eliminate polling while waiting for window to open
authorMichael Brown <mcb30@ipxe.org>
Fri, 24 Jun 2011 16:59:43 +0000 (17:59 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 28 Jun 2011 13:45:12 +0000 (14:45 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/net/tcp/http.c

index 15f88b31947463d73b354858a20d224125750ce5..432e5cd9b9c71dfb2db8dc1bcc235c19404d5ca6 100644 (file)
@@ -48,6 +48,12 @@ FILE_LICENCE ( GPL2_OR_LATER );
 
 FEATURE ( FEATURE_PROTOCOL, "HTTP", DHCP_EB_FEATURE_HTTP, 1 );
 
+/** HTTP transmission state */
+enum http_tx_state {
+       HTTP_TX_REQUEST = 0,
+       HTTP_TX_DONE,
+};
+
 /** HTTP receive state */
 enum http_rx_state {
        HTTP_RX_RESPONSE = 0,
@@ -75,6 +81,8 @@ struct http_request {
 
        /** TX process */
        struct process process;
+       /** TX state */
+       enum http_tx_state tx_state;
 
        /** HTTP response code */
        unsigned int response;
@@ -498,49 +506,55 @@ static void http_step ( struct http_request *http ) {
        int rc;
        int request_len = unparse_uri ( NULL, 0, http->uri,
                                        URI_PATH_BIT | URI_QUERY_BIT );
+       char request[ request_len + 1 /* NUL */ ];
 
-       if ( xfer_window ( &http->socket ) ) {
-               char request[request_len + 1];
+       /* Do nothing if we have already transmitted the request */
+       if ( http->tx_state != HTTP_TX_REQUEST )
+               return;
 
-               /* Construct path?query request */
-               unparse_uri ( request, sizeof ( request ), http->uri,
-                             URI_PATH_BIT | URI_QUERY_BIT );
+       /* Do nothing until socket is ready */
+       if ( ! xfer_window ( &http->socket ) )
+               return;
 
-               /* We want to execute only once */
-               process_del ( &http->process );
+       /* Construct path?query request */
+       unparse_uri ( request, sizeof ( request ), http->uri,
+                     URI_PATH_BIT | URI_QUERY_BIT );
 
-               /* Construct authorisation, if applicable */
-               if ( user ) {
-                       /* Make "user:password" string from decoded fields */
-                       snprintf ( ( ( char * ) user_pw ), sizeof ( user_pw ),
-                                  "%s:%s", user, password );
+       /* Construct authorisation, if applicable */
+       if ( user ) {
+               /* Make "user:password" string from decoded fields */
+               snprintf ( ( ( char * ) user_pw ), sizeof ( user_pw ),
+                          "%s:%s", user, password );
 
-                       /* Base64-encode the "user:password" string */
-                       base64_encode ( user_pw, user_pw_len, user_pw_base64 );
-               }
+               /* Base64-encode the "user:password" string */
+               base64_encode ( user_pw, user_pw_len, user_pw_base64 );
+       }
 
-               /* Send GET request */
-               if ( ( rc = xfer_printf ( &http->socket,
-                                         "GET %s%s HTTP/1.1\r\n"
-                                         "User-Agent: iPXE/" VERSION "\r\n"
-                                         "%s%s%s"
-                                         "Host: %s\r\n"
-                                         "\r\n",
-                                         http->uri->path ? "" : "/",
-                                         request,
-                                         ( user ?
-                                           "Authorization: Basic " : "" ),
-                                         ( user ? user_pw_base64 : "" ),
-                                         ( user ? "\r\n" : "" ),
-                                         host ) ) != 0 ) {
-                       http_done ( http, rc );
-               }
+       /* Mark request as transmitted */
+       http->tx_state = HTTP_TX_DONE;
+
+       /* Send GET request */
+       if ( ( rc = xfer_printf ( &http->socket,
+                                 "GET %s%s HTTP/1.1\r\n"
+                                 "User-Agent: iPXE/" VERSION "\r\n"
+                                 "%s%s%s"
+                                 "Host: %s\r\n"
+                                 "\r\n",
+                                 http->uri->path ? "" : "/",
+                                 request,
+                                 ( user ?
+                                   "Authorization: Basic " : "" ),
+                                 ( user ? user_pw_base64 : "" ),
+                                 ( user ? "\r\n" : "" ),
+                                 host ) ) != 0 ) {
+               http_done ( http, rc );
        }
 }
 
 /** HTTP socket interface operations */
 static struct interface_operation http_socket_operations[] = {
        INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ),
+       INTF_OP ( xfer_window_changed, struct http_request *, http_step ),
        INTF_OP ( intf_close, struct http_request *, http_done ),
 };
 
@@ -561,7 +575,7 @@ static struct interface_descriptor http_xfer_desc =
 
 /** HTTP process descriptor */
 static struct process_descriptor http_process_desc =
-       PROC_DESC ( struct http_request, process, http_step );
+       PROC_DESC_ONCE ( struct http_request, process, http_step );
 
 /**
  * Initiate an HTTP connection, with optional filter