mirror of https://github.com/ipxe/ipxe.git
565 lines
14 KiB
C
565 lines
14 KiB
C
#ifndef _IPXE_HTTP_H
|
|
#define _IPXE_HTTP_H
|
|
|
|
/** @file
|
|
*
|
|
* Hyper Text Transport Protocol
|
|
*
|
|
*/
|
|
|
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|
|
|
#include <stdint.h>
|
|
#include <ipxe/refcnt.h>
|
|
#include <ipxe/interface.h>
|
|
#include <ipxe/iobuf.h>
|
|
#include <ipxe/process.h>
|
|
#include <ipxe/retry.h>
|
|
#include <ipxe/linebuf.h>
|
|
#include <ipxe/pool.h>
|
|
#include <ipxe/tables.h>
|
|
#include <ipxe/ntlm.h>
|
|
|
|
struct http_transaction;
|
|
struct http_connection;
|
|
|
|
/******************************************************************************
|
|
*
|
|
* HTTP URI schemes
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** HTTP default port */
|
|
#define HTTP_PORT 80
|
|
|
|
/** HTTPS default port */
|
|
#define HTTPS_PORT 443
|
|
|
|
/** An HTTP URI scheme */
|
|
struct http_scheme {
|
|
/** Scheme name (e.g. "http" or "https") */
|
|
const char *name;
|
|
/** Default port */
|
|
unsigned int port;
|
|
/** Transport-layer filter (if any)
|
|
*
|
|
* @v conn HTTP connection
|
|
* @ret rc Return status code
|
|
*/
|
|
int ( * filter ) ( struct http_connection *conn );
|
|
};
|
|
|
|
/** HTTP scheme table */
|
|
#define HTTP_SCHEMES __table ( struct http_scheme, "http_schemes" )
|
|
|
|
/** Declare an HTTP scheme */
|
|
#define __http_scheme __table_entry ( HTTP_SCHEMES, 01 )
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Connections
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** An HTTP connection
|
|
*
|
|
* This represents a potentially reusable connection to an HTTP
|
|
* server.
|
|
*/
|
|
struct http_connection {
|
|
/** Reference count */
|
|
struct refcnt refcnt;
|
|
/** Connection URI
|
|
*
|
|
* This encapsulates the server (and protocol) used for the
|
|
* connection. This may be the origin server or a proxy
|
|
* server.
|
|
*/
|
|
struct uri *uri;
|
|
/** HTTP scheme */
|
|
struct http_scheme *scheme;
|
|
/** Transport layer interface */
|
|
struct interface socket;
|
|
/** Data transfer interface */
|
|
struct interface xfer;
|
|
/** Pooled connection */
|
|
struct pooled_connection pool;
|
|
};
|
|
|
|
/******************************************************************************
|
|
*
|
|
* HTTP methods
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** An HTTP method */
|
|
struct http_method {
|
|
/** Method name (e.g. "GET" or "POST") */
|
|
const char *name;
|
|
};
|
|
|
|
extern struct http_method http_head;
|
|
extern struct http_method http_get;
|
|
extern struct http_method http_post;
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Requests
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** HTTP Digest authentication client nonce count
|
|
*
|
|
* We choose to generate a new client nonce each time.
|
|
*/
|
|
#define HTTP_DIGEST_NC "00000001"
|
|
|
|
/** HTTP Digest authentication client nonce length
|
|
*
|
|
* We choose to use a 32-bit hex client nonce.
|
|
*/
|
|
#define HTTP_DIGEST_CNONCE_LEN 8
|
|
|
|
/** HTTP Digest authentication response length
|
|
*
|
|
* The Digest authentication response is a Base16-encoded 16-byte MD5
|
|
* checksum.
|
|
*/
|
|
#define HTTP_DIGEST_RESPONSE_LEN 32
|
|
|
|
/** HTTP request range descriptor */
|
|
struct http_request_range {
|
|
/** Range start */
|
|
size_t start;
|
|
/** Range length, or zero for no range request */
|
|
size_t len;
|
|
};
|
|
|
|
/** HTTP request content descriptor */
|
|
struct http_request_content {
|
|
/** Content type (if any) */
|
|
const char *type;
|
|
/** Content data (if any) */
|
|
const void *data;
|
|
/** Content length */
|
|
size_t len;
|
|
};
|
|
|
|
/** HTTP request Basic authentication descriptor */
|
|
struct http_request_auth_basic {
|
|
/** Username */
|
|
const char *username;
|
|
/** Password */
|
|
const char *password;
|
|
};
|
|
|
|
/** HTTP request Digest authentication descriptor */
|
|
struct http_request_auth_digest {
|
|
/** Username */
|
|
const char *username;
|
|
/** Quality of protection */
|
|
const char *qop;
|
|
/** Algorithm */
|
|
const char *algorithm;
|
|
/** Client nonce */
|
|
char cnonce[ HTTP_DIGEST_CNONCE_LEN + 1 /* NUL */ ];
|
|
/** Response */
|
|
char response[ HTTP_DIGEST_RESPONSE_LEN + 1 /* NUL */ ];
|
|
};
|
|
|
|
/** HTTP request NTLM authentication descriptor */
|
|
struct http_request_auth_ntlm {
|
|
/** Username */
|
|
const char *username;
|
|
/** LAN Manager response */
|
|
struct ntlm_lm_response lm;
|
|
/** NT response */
|
|
struct ntlm_nt_response nt;
|
|
/** Authenticate message length */
|
|
size_t len;
|
|
};
|
|
|
|
/** HTTP request authentication descriptor */
|
|
struct http_request_auth {
|
|
/** Authentication scheme (if any) */
|
|
struct http_authentication *auth;
|
|
/** Per-scheme information */
|
|
union {
|
|
/** Basic authentication descriptor */
|
|
struct http_request_auth_basic basic;
|
|
/** Digest authentication descriptor */
|
|
struct http_request_auth_digest digest;
|
|
/** NTLM authentication descriptor */
|
|
struct http_request_auth_ntlm ntlm;
|
|
};
|
|
};
|
|
|
|
/** An HTTP request
|
|
*
|
|
* This represents a single request to be sent to a server, including
|
|
* the values required to construct all headers.
|
|
*
|
|
* Pointers within this structure must point to storage which is
|
|
* guaranteed to remain valid for the lifetime of the containing HTTP
|
|
* transaction.
|
|
*/
|
|
struct http_request {
|
|
/** Method */
|
|
struct http_method *method;
|
|
/** Request URI string */
|
|
const char *uri;
|
|
/** Server host name */
|
|
const char *host;
|
|
/** Range descriptor */
|
|
struct http_request_range range;
|
|
/** Content descriptor */
|
|
struct http_request_content content;
|
|
/** Authentication descriptor */
|
|
struct http_request_auth auth;
|
|
};
|
|
|
|
/** An HTTP request header */
|
|
struct http_request_header {
|
|
/** Header name (e.g. "User-Agent") */
|
|
const char *name;
|
|
/** Construct remaining header line
|
|
*
|
|
* @v http HTTP transaction
|
|
* @v buf Buffer
|
|
* @v len Length of buffer
|
|
* @ret len Header length if present, or negative error
|
|
*/
|
|
int ( * format ) ( struct http_transaction *http, char *buf,
|
|
size_t len );
|
|
};
|
|
|
|
/** HTTP request header table */
|
|
#define HTTP_REQUEST_HEADERS \
|
|
__table ( struct http_request_header, "http_request_headers" )
|
|
|
|
/** Declare an HTTP request header */
|
|
#define __http_request_header __table_entry ( HTTP_REQUEST_HEADERS, 01 )
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Responses
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** HTTP response transfer descriptor */
|
|
struct http_response_transfer {
|
|
/** Transfer encoding */
|
|
struct http_transfer_encoding *encoding;
|
|
};
|
|
|
|
/** HTTP response content descriptor */
|
|
struct http_response_content {
|
|
/** Content length (may be zero) */
|
|
size_t len;
|
|
/** Content encoding */
|
|
struct http_content_encoding *encoding;
|
|
};
|
|
|
|
/** HTTP response Basic authorization descriptor */
|
|
struct http_response_auth_basic {
|
|
};
|
|
|
|
/** HTTP response Digest authorization descriptor */
|
|
struct http_response_auth_digest {
|
|
/** Realm */
|
|
const char *realm;
|
|
/** Quality of protection */
|
|
const char *qop;
|
|
/** Algorithm */
|
|
const char *algorithm;
|
|
/** Nonce */
|
|
const char *nonce;
|
|
/** Opaque */
|
|
const char *opaque;
|
|
};
|
|
|
|
/** HTTP response NTLM authorization descriptor */
|
|
struct http_response_auth_ntlm {
|
|
/** Challenge message */
|
|
struct ntlm_challenge *challenge;
|
|
/** Challenge information */
|
|
struct ntlm_challenge_info info;
|
|
};
|
|
|
|
/** HTTP response authorization descriptor */
|
|
struct http_response_auth {
|
|
/** Authentication scheme (if any) */
|
|
struct http_authentication *auth;
|
|
/** Per-scheme information */
|
|
union {
|
|
/** Basic authorization descriptor */
|
|
struct http_response_auth_basic basic;
|
|
/** Digest authorization descriptor */
|
|
struct http_response_auth_digest digest;
|
|
/** NTLM authorization descriptor */
|
|
struct http_response_auth_ntlm ntlm;
|
|
};
|
|
};
|
|
|
|
/** An HTTP response
|
|
*
|
|
* This represents a single response received from the server,
|
|
* including all values parsed from headers.
|
|
*
|
|
* Pointers within this structure may point into the raw response
|
|
* buffer, and so should be invalidated when the response buffer is
|
|
* modified or discarded.
|
|
*/
|
|
struct http_response {
|
|
/** Raw response header lines
|
|
*
|
|
* This is the raw response data received from the server, up
|
|
* to and including the terminating empty line. String
|
|
* pointers within the response may point into this data
|
|
* buffer; NUL terminators will be added (overwriting the
|
|
* original terminating characters) as needed.
|
|
*/
|
|
struct line_buffer headers;
|
|
/** Status code
|
|
*
|
|
* This is the raw HTTP numeric status code (e.g. 404).
|
|
*/
|
|
unsigned int status;
|
|
/** Return status code
|
|
*
|
|
* This is the iPXE return status code corresponding to the
|
|
* HTTP status code (e.g. -ENOENT).
|
|
*/
|
|
int rc;
|
|
/** Redirection location */
|
|
const char *location;
|
|
/** Transfer descriptor */
|
|
struct http_response_transfer transfer;
|
|
/** Content descriptor */
|
|
struct http_response_content content;
|
|
/** Authorization descriptor */
|
|
struct http_response_auth auth;
|
|
/** Retry delay (in seconds) */
|
|
unsigned int retry_after;
|
|
/** Flags */
|
|
unsigned int flags;
|
|
};
|
|
|
|
/** HTTP response flags */
|
|
enum http_response_flags {
|
|
/** Keep connection alive after close */
|
|
HTTP_RESPONSE_KEEPALIVE = 0x0001,
|
|
/** Content length specified */
|
|
HTTP_RESPONSE_CONTENT_LEN = 0x0002,
|
|
/** Transaction may be retried on failure */
|
|
HTTP_RESPONSE_RETRY = 0x0004,
|
|
};
|
|
|
|
/** An HTTP response header */
|
|
struct http_response_header {
|
|
/** Header name (e.g. "Transfer-Encoding") */
|
|
const char *name;
|
|
/** Parse header line
|
|
*
|
|
* @v http HTTP transaction
|
|
* @v line Remaining header line
|
|
* @ret rc Return status code
|
|
*/
|
|
int ( * parse ) ( struct http_transaction *http, char *line );
|
|
};
|
|
|
|
/** HTTP response header table */
|
|
#define HTTP_RESPONSE_HEADERS \
|
|
__table ( struct http_response_header, "http_response_headers" )
|
|
|
|
/** Declare an HTTP response header */
|
|
#define __http_response_header __table_entry ( HTTP_RESPONSE_HEADERS, 01 )
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Transactions
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** HTTP transaction state */
|
|
struct http_state {
|
|
/** Transmit data
|
|
*
|
|
* @v http HTTP transaction
|
|
* @ret rc Return status code
|
|
*/
|
|
int ( * tx ) ( struct http_transaction *http );
|
|
/** Receive data
|
|
*
|
|
* @v http HTTP transaction
|
|
* @v iobuf I/O buffer (may be claimed)
|
|
* @ret rc Return status code
|
|
*/
|
|
int ( * rx ) ( struct http_transaction *http,
|
|
struct io_buffer **iobuf );
|
|
/** Server connection closed
|
|
*
|
|
* @v http HTTP transaction
|
|
* @v rc Reason for close
|
|
*/
|
|
void ( * close ) ( struct http_transaction *http, int rc );
|
|
};
|
|
|
|
/** An HTTP transaction */
|
|
struct http_transaction {
|
|
/** Reference count */
|
|
struct refcnt refcnt;
|
|
/** Data transfer interface */
|
|
struct interface xfer;
|
|
/** Content-decoded interface */
|
|
struct interface content;
|
|
/** Transfer-decoded interface */
|
|
struct interface transfer;
|
|
/** Server connection */
|
|
struct interface conn;
|
|
/** Transmit process */
|
|
struct process process;
|
|
/** Reconnection timer */
|
|
struct retry_timer timer;
|
|
|
|
/** Request URI */
|
|
struct uri *uri;
|
|
/** Request */
|
|
struct http_request request;
|
|
/** Response */
|
|
struct http_response response;
|
|
/** Temporary line buffer */
|
|
struct line_buffer linebuf;
|
|
|
|
/** Transaction state */
|
|
struct http_state *state;
|
|
/** Accumulated transfer-decoded length */
|
|
size_t len;
|
|
/** Chunk length remaining */
|
|
size_t remaining;
|
|
};
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Transfer encoding
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** An HTTP transfer encoding */
|
|
struct http_transfer_encoding {
|
|
/** Name */
|
|
const char *name;
|
|
/** Initialise transfer encoding
|
|
*
|
|
* @v http HTTP transaction
|
|
* @ret rc Return status code
|
|
*/
|
|
int ( * init ) ( struct http_transaction *http );
|
|
/** Receive data state */
|
|
struct http_state state;
|
|
};
|
|
|
|
/** HTTP transfer encoding table */
|
|
#define HTTP_TRANSFER_ENCODINGS \
|
|
__table ( struct http_transfer_encoding, "http_transfer_encodings" )
|
|
|
|
/** Declare an HTTP transfer encoding */
|
|
#define __http_transfer_encoding __table_entry ( HTTP_TRANSFER_ENCODINGS, 01 )
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Content encoding
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** An HTTP content encoding */
|
|
struct http_content_encoding {
|
|
/** Name */
|
|
const char *name;
|
|
/** Check if content encoding is supported for this request
|
|
*
|
|
* @v http HTTP transaction
|
|
* @ret supported Content encoding is supported for this request
|
|
*/
|
|
int ( * supported ) ( struct http_transaction *http );
|
|
/** Initialise content encoding
|
|
*
|
|
* @v http HTTP transaction
|
|
* @ret rc Return status code
|
|
*/
|
|
int ( * init ) ( struct http_transaction *http );
|
|
};
|
|
|
|
/** HTTP content encoding table */
|
|
#define HTTP_CONTENT_ENCODINGS \
|
|
__table ( struct http_content_encoding, "http_content_encodings" )
|
|
|
|
/** Declare an HTTP content encoding */
|
|
#define __http_content_encoding __table_entry ( HTTP_CONTENT_ENCODINGS, 01 )
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Authentication
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** An HTTP authentication scheme */
|
|
struct http_authentication {
|
|
/** Name (e.g. "Digest") */
|
|
const char *name;
|
|
/** Parse remaining "WWW-Authenticate" header line
|
|
*
|
|
* @v http HTTP transaction
|
|
* @v line Remaining header line
|
|
* @ret rc Return status code
|
|
*/
|
|
int ( * parse ) ( struct http_transaction *http, char *line );
|
|
/** Perform authentication
|
|
*
|
|
* @v http HTTP transaction
|
|
* @ret rc Return status code
|
|
*/
|
|
int ( * authenticate ) ( struct http_transaction *http );
|
|
/** Construct remaining "Authorization" header line
|
|
*
|
|
* @v http HTTP transaction
|
|
* @v buf Buffer
|
|
* @v len Length of buffer
|
|
* @ret len Header length if present, or negative error
|
|
*/
|
|
int ( * format ) ( struct http_transaction *http, char *buf,
|
|
size_t len );
|
|
};
|
|
|
|
/** HTTP authentication scheme table */
|
|
#define HTTP_AUTHENTICATIONS \
|
|
__table ( struct http_authentication, "http_authentications" )
|
|
|
|
/** Declare an HTTP authentication scheme */
|
|
#define __http_authentication __table_entry ( HTTP_AUTHENTICATIONS, 01 )
|
|
|
|
/******************************************************************************
|
|
*
|
|
* General
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
extern char * http_token ( char **line, char **value );
|
|
extern int http_connect ( struct interface *xfer, struct uri *uri );
|
|
extern int http_open ( struct interface *xfer, struct http_method *method,
|
|
struct uri *uri, struct http_request_range *range,
|
|
struct http_request_content *content );
|
|
extern int http_open_uri ( struct interface *xfer, struct uri *uri );
|
|
|
|
#endif /* _IPXE_HTTP_H */
|