iPXE
Defines | Functions | Variables
httpconn.c File Reference

Hyper Text Transfer Protocol (HTTP) connection management. More...

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/tcpip.h>
#include <ipxe/uri.h>
#include <ipxe/timer.h>
#include <ipxe/xfer.h>
#include <ipxe/open.h>
#include <ipxe/pool.h>
#include <ipxe/http.h>

Go to the source code of this file.

Defines

#define HTTP_CONN_EXPIRY   ( 10 * TICKS_PER_SEC )
 HTTP pooled connection expiry time.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static LIST_HEAD (http_connection_pool)
 HTTP connection pool.
static struct http_schemehttp_scheme (struct uri *uri)
 Identify HTTP scheme.
static void http_conn_free (struct refcnt *refcnt)
 Free HTTP connection.
static void http_conn_close (struct http_connection *conn, int rc)
 Close HTTP connection.
static void http_conn_expired (struct pooled_connection *pool)
 Disconnect idle HTTP connection.
static int http_conn_socket_deliver (struct http_connection *conn, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Receive data from transport layer interface.
static void http_conn_socket_close (struct http_connection *conn, int rc)
 Close HTTP connection transport layer interface.
static void http_conn_xfer_recycle (struct http_connection *conn)
 Recycle this connection after closing.
static void http_conn_xfer_close (struct http_connection *conn, int rc)
 Close HTTP connection data transfer interface.
int http_connect (struct interface *xfer, struct uri *uri)
 Connect to an HTTP server.

Variables

static struct interface_operation http_conn_socket_operations []
 HTTP connection socket interface operations.
static struct interface_descriptor http_conn_socket_desc
 HTTP connection socket interface descriptor.
static struct interface_operation http_conn_xfer_operations []
 HTTP connection data transfer interface operations.
static struct interface_descriptor http_conn_xfer_desc
 HTTP connection data transfer interface descriptor.

Detailed Description

Hyper Text Transfer Protocol (HTTP) connection management.

Definition in file httpconn.c.


Define Documentation

#define HTTP_CONN_EXPIRY   ( 10 * TICKS_PER_SEC )

HTTP pooled connection expiry time.

Definition at line 46 of file httpconn.c.

Referenced by http_conn_xfer_close().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static LIST_HEAD ( http_connection_pool  ) [static]

HTTP connection pool.

static struct http_scheme* http_scheme ( struct uri uri) [static, read]

Identify HTTP scheme.

Parameters:
uriURI
Return values:
schemeHTTP scheme, or NULL

Definition at line 57 of file httpconn.c.

References for_each_table_entry, HTTP_SCHEMES, http_scheme::name, NULL, uri::scheme, and strcmp().

Referenced by http_connect().

                                                            {
        struct http_scheme *scheme;

        /* Sanity check */
        if ( ! uri->scheme )
                return NULL;

        /* Identify scheme */
        for_each_table_entry ( scheme, HTTP_SCHEMES ) {
                if ( strcmp ( uri->scheme, scheme->name ) == 0 )
                        return scheme;
        }

        return NULL;
}
static void http_conn_free ( struct refcnt refcnt) [static]

Free HTTP connection.

Parameters:
refcntReference count

Definition at line 78 of file httpconn.c.

References container_of, free, http_connection::uri, and uri_put().

Referenced by http_connect().

                                                     {
        struct http_connection *conn =
                container_of ( refcnt, struct http_connection, refcnt );

        /* Free connection */
        uri_put ( conn->uri );
        free ( conn );
}
static void http_conn_close ( struct http_connection conn,
int  rc 
) [static]

Close HTTP connection.

Parameters:
connHTTP connection
rcReason for close

Definition at line 93 of file httpconn.c.

References DBGC, DBGC2, uri::host, intf_shutdown(), http_scheme::name, http_connection::pool, pool_del(), http_connection::scheme, http_connection::socket, strerror(), http_connection::uri, and http_connection::xfer.

Referenced by http_conn_expired(), http_conn_socket_close(), http_conn_xfer_close(), and http_connect().

                                                                     {

        /* Remove from connection pool, if applicable */
        pool_del ( &conn->pool );

        /* Shut down interfaces */
        intf_shutdown ( &conn->socket, rc );
        intf_shutdown ( &conn->xfer, rc );
        if ( rc == 0 ) {
                DBGC2 ( conn, "HTTPCONN %p closed %s://%s\n",
                        conn, conn->scheme->name, conn->uri->host );
        } else {
                DBGC ( conn, "HTTPCONN %p closed %s://%s: %s\n",
                       conn, conn->scheme->name, conn->uri->host,
                       strerror ( rc ) );
        }
}
static void http_conn_expired ( struct pooled_connection pool) [static]

Disconnect idle HTTP connection.

Parameters:
poolPooled connection

Definition at line 116 of file httpconn.c.

References container_of, and http_conn_close().

Referenced by http_connect().

                                                                 {
        struct http_connection *conn =
                container_of ( pool, struct http_connection, pool );

        /* Close connection */
        http_conn_close ( conn, 0 /* Not an error to close idle connection */ );
}
static int http_conn_socket_deliver ( struct http_connection conn,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Receive data from transport layer interface.

Parameters:
httpHTTP connection
iobufI/O buffer
metaTransfer metadata
Return values:
rcReturn status code

Definition at line 132 of file httpconn.c.

References http_connection::pool, http_connection::xfer, and xfer_deliver().

                                                                   {

        /* Mark connection as alive */
        pool_alive ( &conn->pool );

        /* Pass on to data transfer interface */
        return xfer_deliver ( &conn->xfer, iobuf, meta );
}
static void http_conn_socket_close ( struct http_connection conn,
int  rc 
) [static]

Close HTTP connection transport layer interface.

Parameters:
httpHTTP connection
rcReason for close

Definition at line 149 of file httpconn.c.

References http_conn_close(), http_connection::pool, pool_reopen(), and http_connection::xfer.

                                                                            {

        /* If we are reopenable (i.e. we are a recycled connection
         * from the connection pool, and we have received no data from
         * the underlying socket since we were pooled), then suggest
         * that the client should reopen the connection.
         */
        if ( pool_is_reopenable ( &conn->pool ) )
                pool_reopen ( &conn->xfer );

        /* Close the connection */
        http_conn_close ( conn, rc );
}
static void http_conn_xfer_recycle ( struct http_connection conn) [static]

Recycle this connection after closing.

Parameters:
httpHTTP connection

Definition at line 168 of file httpconn.c.

References DBGC2, and http_connection::pool.

                                                                    {

        /* Mark connection as recyclable */
        pool_recyclable ( &conn->pool );
        DBGC2 ( conn, "HTTPCONN %p keepalive enabled\n", conn );
}
static void http_conn_xfer_close ( struct http_connection conn,
int  rc 
) [static]

Close HTTP connection data transfer interface.

Parameters:
connHTTP connection
rcReason for close

Definition at line 181 of file httpconn.c.

References DBGC2, uri::host, http_conn_close(), HTTP_CONN_EXPIRY, intf_restart(), http_scheme::name, http_connection::pool, pool_add(), http_connection::scheme, http_connection::uri, and http_connection::xfer.

                                                                          {

        /* Add to the connection pool if keepalive is enabled and no
         * error occurred.
         */
        if ( ( rc == 0 ) && pool_is_recyclable ( &conn->pool ) ) {
                intf_restart ( &conn->xfer, rc );
                pool_add ( &conn->pool, &http_connection_pool,
                           HTTP_CONN_EXPIRY );
                DBGC2 ( conn, "HTTPCONN %p pooled %s://%s\n",
                        conn, conn->scheme->name, conn->uri->host );
                return;
        }

        /* Otherwise, close the connection */
        http_conn_close ( conn, rc );
}
int http_connect ( struct interface xfer,
struct uri uri 
)

Connect to an HTTP server.

Parameters:
xferData transfer interface
uriConnection URI
Return values:
rcReturn status code

HTTP connections are pooled. The caller should be prepared to receive a pool_reopen() message.

Definition at line 235 of file httpconn.c.

References assert, DBGC2, EINVAL, ENOMEM, ENOTSUP, http_scheme::filter, uri::host, htons, http_conn_close(), http_conn_expired(), http_conn_free(), http_scheme(), intf_init(), intf_plug_plug(), list_for_each_entry_reverse, memset(), http_scheme::name, NULL, http_connection::pool, pool_del(), http_scheme::port, port, rc, ref_init, ref_put, http_connection::refcnt, http_connection::scheme, SOCK_STREAM, http_connection::socket, sockaddr_tcpip::st_port, strcmp(), strerror(), http_connection::uri, uri_get(), uri_port(), http_connection::xfer, xfer_open_named_socket(), and zalloc().

Referenced by http_open(), and http_reopen().

                                                             {
        struct http_connection *conn;
        struct http_scheme *scheme;
        struct sockaddr_tcpip server;
        struct interface *socket;
        unsigned int port;
        int rc;

        /* Identify scheme */
        scheme = http_scheme ( uri );
        if ( ! scheme )
                return -ENOTSUP;

        /* Sanity check */
        if ( ! uri->host )
                return -EINVAL;

        /* Identify port */
        port = uri_port ( uri, scheme->port );

        /* Look for a reusable connection in the pool.  Reuse the most
         * recent connection in order to accommodate authentication
         * schemes that break the stateless nature of HTTP and rely on
         * the same connection being reused for authentication
         * responses.
         */
        list_for_each_entry_reverse ( conn, &http_connection_pool, pool.list ) {

                /* Sanity checks */
                assert ( conn->uri != NULL );
                assert ( conn->uri->host != NULL );

                /* Reuse connection, if possible */
                if ( ( scheme == conn->scheme ) &&
                     ( strcmp ( uri->host, conn->uri->host ) == 0 ) &&
                     ( port == uri_port ( conn->uri, scheme->port ) ) ) {

                        /* Remove from connection pool, stop timer,
                         * attach to parent interface, and return.
                         */
                        pool_del ( &conn->pool );
                        intf_plug_plug ( &conn->xfer, xfer );
                        DBGC2 ( conn, "HTTPCONN %p reused %s://%s:%d\n", conn,
                                conn->scheme->name, conn->uri->host, port );
                        return 0;
                }
        }

        /* Allocate and initialise structure */
        conn = zalloc ( sizeof ( *conn ) );
        if ( ! conn ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        ref_init ( &conn->refcnt, http_conn_free );
        conn->uri = uri_get ( uri );
        conn->scheme = scheme;
        intf_init ( &conn->socket, &http_conn_socket_desc, &conn->refcnt );
        intf_init ( &conn->xfer, &http_conn_xfer_desc, &conn->refcnt );
        pool_init ( &conn->pool, http_conn_expired, &conn->refcnt );

        /* Open socket */
        memset ( &server, 0, sizeof ( server ) );
        server.st_port = htons ( port );
        socket = &conn->socket;
        if ( scheme->filter &&
             ( ( rc = scheme->filter ( socket, uri->host, &socket ) ) != 0 ) )
                goto err_filter;
        if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM,
                                             ( struct sockaddr * ) &server,
                                             uri->host, NULL ) ) != 0 )
                goto err_open;

        /* Attach to parent interface, mortalise self, and return */
        intf_plug_plug ( &conn->xfer, xfer );
        ref_put ( &conn->refcnt );

        DBGC2 ( conn, "HTTPCONN %p created %s://%s:%d\n", conn,
                conn->scheme->name, conn->uri->host, port );
        return 0;

 err_open:
 err_filter:
        DBGC2 ( conn, "HTTPCONN %p could not create %s://%s:%d: %s\n", conn,
                conn->scheme->name, conn->uri->host, port, strerror ( rc ) );
        http_conn_close ( conn, rc );
        ref_put ( &conn->refcnt );
 err_alloc:
        return rc;
}

Variable Documentation

Initial value:

HTTP connection socket interface operations.

Definition at line 200 of file httpconn.c.

Initial value:

HTTP connection socket interface descriptor.

Definition at line 208 of file httpconn.c.

Initial value:

HTTP connection data transfer interface operations.

Definition at line 213 of file httpconn.c.

Initial value:

HTTP connection data transfer interface descriptor.

Definition at line 221 of file httpconn.c.