The whole HTTP logic is not contained here. Only generic supporting routines are here.
#include "common.h"
#include "nodes.h"
#include "http.h"
#include "sockets.h"
#include "bsched.h"
#include "ioheader.h"
#include "version.h"
#include "token.h"
#include "clock.h"
#include "lib/atoms.h"
#include "lib/getline.h"
#include "lib/glib-missing.h"
#include "lib/header.h"
#include "lib/tm.h"
#include "lib/walloc.h"
#include "if/gnet_property_priv.h"
#include "lib/override.h"
Data Structures | |
struct | http_async |
An asynchronous HTTP request. More... | |
Defines | |
#define | HTTP_ASYNC_MAGIC 0xa91cf3eeU |
#define | HA_F_FREED 0x00000001 /**< Structure has been logically freed */ |
Structure has been logically freed. | |
#define | HA_F_SUBREQ 0x00000002 /**< Children request now has control */ |
Children request now has control. | |
Enumerations | |
enum | http_reqtype { HTTP_HEAD = 0, HTTP_GET, HTTP_POST, NUM_HTTP_REQTYPES } |
Functions | |
RCSID ("$Id:http.c, v 1.46 2005/12/17 10:33:09 cbiere Exp $") | |
gboolean | http_send_status (struct gnutella_socket *s, gint code, gboolean keep_alive, http_extra_desc_t *hev, gint hevcnt, const gchar *reason,...) |
Send HTTP status on socket, with code and reason. | |
void | http_hostname_add (gchar *buf, gint *retval, gpointer unused_arg, guint32 flags) |
HTTP status callback. | |
gint | code_message_parse (const gchar *line, const gchar **msg) |
Parse status messages formed of leading digit numbers, then an optional message. | |
gint | http_status_parse (const gchar *line, const gchar *proto, const gchar **msg, guint *major, guint *minor) |
Parse protocol status line, and return the status code, and optionally a pointer within the string where the status message starts (if `msg' is a non-null pointer), and the protocol major/minor (if `major' and `minor' are non-null). | |
gboolean | http_extract_version (const gchar *request, gint len, guint *major, guint *minor) |
Extract HTTP version major/minor out of the given request, whose string length is `len' bytes. | |
const gchar * | http_url_strerror (http_url_error_t errnum) |
gboolean | http_url_parse (const gchar *url, guint16 *port, const gchar **host, const gchar **path) |
Parse HTTP url and extract the IP/port we need to connect to. | |
http_buffer_t * | http_buffer_alloc (gchar *buf, size_t len, size_t written) |
Allocate HTTP buffer, capable of holding data at `buf', of `len' bytes, and whose `written' bytes have already been sent out. | |
void | http_buffer_free (http_buffer_t *b) |
Dispose of HTTP buffer. | |
gint | http_content_range_parse (const gchar *buf, filesize_t *start, filesize_t *end, filesize_t *total) |
Parses the content of a Content-Range header. | |
GSList * | http_range_add (GSList *list, filesize_t start, filesize_t end, const gchar *field, const gchar *vendor, gboolean *ignored) |
Add a new http_range_t object within the sorted list. | |
GSList * | http_range_parse (const gchar *field, const gchar *value, filesize_t size, const gchar *vendor) |
Parse a Range: header in the request, returning the list of ranges that are enumerated. | |
void | http_range_free (GSList *list) |
Free list of http_range_t objects. | |
filesize_t | http_range_size (const GSList *list) |
const gchar * | http_range_to_string (const GSList *list) |
gboolean | http_range_contains (GSList *ranges, filesize_t from, filesize_t to) |
Checks whether range contains the contiguous [from, to] interval. | |
http_range_t * | http_range_clone (http_range_t *range) |
GSList * | http_range_merge (GSList *old_list, GSList *new_list) |
const gchar * | http_async_strerror (guint errnum) |
const gchar * | http_async_info (gpointer handle, const gchar **req, gchar **path, host_addr_t *addr, guint16 *port) |
Get URL and request information, given opaque handle. | |
void | http_async_set_opaque (gpointer handle, gpointer data, http_user_free_t fn) |
Set user-defined opaque data, which can optionally be freed via `fn' if a non-NULL function pointer is given. | |
gpointer | http_async_get_opaque (gpointer handle) |
Retrieve user-defined opaque data. | |
void | http_async_free_recursive (struct http_async *ha) |
Free this HTTP asynchronous request handler, disposing of all its attached resources, recursively. | |
void | http_async_free (struct http_async *ha) |
Free the root of the HTTP asynchronous request handler, disposing of all its attached resources. | |
void | http_async_free_pending (void) |
Free all structures that have already been logically freed. | |
void | http_async_close (gpointer handle) |
Close request. | |
void | http_async_remove (gpointer handle, http_errtype_t type, gpointer code) |
Cancel request (internal call). | |
void | http_async_cancel (gpointer handle) |
Cancel request (user request). | |
void | http_async_error (gpointer handle, gint code) |
Cancel request (internal error). | |
void | http_async_syserr (gpointer handle, gint code) |
Cancel request (system call error). | |
void | http_async_headerr (gpointer handle, gint code) |
Cancel request (header parsing error). | |
void | http_async_http_error (gpointer handle, struct header *header, gint code, const gchar *message) |
Cancel request (HTTP error). | |
size_t | http_async_build_request (gpointer unused_handle, gchar *buf, size_t len, const gchar *verb, const gchar *path, const gchar *host, guint16 port) |
Default callback invoked to build the HTTP request. | |
http_async * | http_async_create (gchar *url, const host_addr_t addr, guint16 port, enum http_reqtype type, http_header_cb_t header_ind, http_data_cb_t data_ind, http_error_cb_t error_ind, struct http_async *parent) |
Internal creation routine for HTTP asynchronous requests. | |
void | http_async_newstate (struct http_async *ha, http_state_t state) |
Change the request state, and notify listener if any. | |
gpointer | http_async_get (gchar *url, http_header_cb_t header_ind, http_data_cb_t data_ind, http_error_cb_t error_ind) |
Starts an asynchronous HTTP GET request on the specified path. | |
gpointer | http_async_get_addr (gchar *path, const host_addr_t addr, guint16 port, http_header_cb_t header_ind, http_data_cb_t data_ind, http_error_cb_t error_ind) |
Same as http_async_get(), but a path on the server is given and the IP and port to contact are given explicitly. | |
void | http_async_set_op_request (gpointer handle, http_op_request_t op) |
Redefines the building of the HTTP request. | |
void | http_async_on_state_change (gpointer handle, http_state_change_t fn) |
Defines callback to invoke when the request changes states. | |
void | http_async_allow_redirects (gpointer handle, gboolean allow) |
Whether we should follow HTTP redirections (FALSE by default). | |
gboolean | http_subreq_header_ind (gpointer handle, struct header *header, gint code, const gchar *message) |
Interceptor callback for `header_ind' in child requests. | |
void | http_subreq_data_ind (gpointer handle, gchar *data, gint len) |
Interceptor callback for `data_ind' in child requests. | |
void | http_subreq_error_ind (gpointer handle, http_errtype_t error, gpointer val) |
Interceptor callback for `error_ind' in child requests. | |
gboolean | http_async_subrequest (struct http_async *parent, gchar *url, enum http_reqtype type) |
Create a child request, to follow redirection transparently. | |
void | http_redirect (struct http_async *ha, gchar *url) |
Redirect current HTTP request to some other URL. | |
void | http_got_data (struct http_async *ha, gboolean eof) |
Tell the user that we got new data for his request. | |
void | http_data_read (gpointer data, gint unused_source, inputevt_cond_t cond) |
Called when data are available on the socket. | |
void | http_got_header (struct http_async *ha, header_t *header) |
Called when the whole server's reply header was parsed. | |
http_state_t | http_async_state (gpointer handle) |
Get the state of the HTTP request. | |
void | call_http_got_header (gpointer obj, header_t *header) |
Called when full header was collected. | |
void | http_header_start (gpointer handle) |
Called when we start receiving the HTTP headers. | |
void | http_async_request_sent (struct http_async *ha) |
Called when the whole HTTP request has been sent out. | |
void | http_async_write_request (gpointer data, gint unused_source, inputevt_cond_t cond) |
I/O callback invoked when we can write more data to the server to finish sending the HTTP request. | |
void | http_async_connected (gpointer handle) |
Callback from the socket layer when the connection to the remote server is made. | |
void | http_async_log_error_dbg (gpointer handle, http_errtype_t type, gpointer v, guint32 dbg_level) |
Error indication callback which logs the error by listing the initial HTTP request and the reported error cause. | |
void | http_async_log_error (gpointer handle, http_errtype_t type, gpointer v) |
Default error indication callback which logs the error by listing the initial HTTP request and the reported error cause. | |
void | err_line_too_long (gpointer obj) |
void | err_header_error (gpointer obj, gint error) |
void | err_input_exception (gpointer obj) |
void | err_input_buffer_full (gpointer obj) |
void | err_header_read_error (gpointer obj, gint error) |
void | err_header_read_eof (gpointer obj) |
void | http_timer (time_t now) |
Called from main timer to expire HTTP requests that take too long. | |
void | http_close (void) |
Shutdown the HTTP module. | |
Variables | |
http_url_error_t | http_url_errno |
Error from http_url_parse(). | |
GSList * | sl_outgoing = NULL |
To spot reply timeouts. | |
gchar * | parse_errstr [] |
const gchar *const | error_str [] |
guint | http_async_errno |
Used to return error codes during setup. | |
const gchar *const | http_verb [NUM_HTTP_REQTYPES] |
GSList * | sl_ha_freed = NULL |
In order to allow detection of logically freed structures when we return from user callbacks, we delay the physical removal of the http_async structure to the clock timer. | |
io_error | http_io_error |
|
Structure has been logically freed.
|
|
Children request now has control.
|
|
|
|
|
|
Called when full header was collected.
|
|
Parse status messages formed of leading digit numbers, then an optional message. The pointer to the start of the message is returned in `msg' if it is non-null.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Whether we should follow HTTP redirections (FALSE by default).
|
|
Default callback invoked to build the HTTP request. The request is to be built in `buf', which is `len' bytes long. The HTTP request is defined by the `verb' ("GET", "HEAD", ...), the `path' to ask for and the `host' to which we are making the request, for suitable "Host:" header emission.
|
|
Cancel request (user request).
|
|
Close request.
|
|
Callback from the socket layer when the connection to the remote server is made.
|
|
Internal creation routine for HTTP asynchronous requests. The URL to request is given by `url'. The type of HTTP request (GET, POST, ...) is given by `type'. If `addr' is non-zero, then `url' is supposed to hold a path, and `port' must also be non-zero. Otherwise, the IP and port are gathered from `url', which must start be something like "http://server:port/path". When all headers are read, optionally call `header_ind' if not-NULL. When data is present, optionally call `data_ind' or close the connection. On error condition during the asynchronous processing, call `error_ind', including when the request is explicitly cancelled (but NOT when it is excplicitly closed). If `parent' is not NULL, then this request is a child request.
|
|
Cancel request (internal error).
|
|
Free the root of the HTTP asynchronous request handler, disposing of all its attached resources.
|
|
Free all structures that have already been logically freed.
|
|
Free this HTTP asynchronous request handler, disposing of all its attached resources, recursively.
|
|
Starts an asynchronous HTTP GET request on the specified path.
On error, `error_ind' will be called, and upon return, the request will be automatically cancelled. |
|
Same as http_async_get(), but a path on the server is given and the IP and port to contact are given explicitly.
|
|
Retrieve user-defined opaque data.
|
|
Cancel request (header parsing error).
|
|
Cancel request (HTTP error).
|
|
Get URL and request information, given opaque handle. This can be used by client code to log request parameters.
|
|
Default error indication callback which logs the error by listing the initial HTTP request and the reported error cause.
|
|
Error indication callback which logs the error by listing the initial HTTP request and the reported error cause. The specified debugging level is explicitly given. |
|
Change the request state, and notify listener if any.
|
|
Defines callback to invoke when the request changes states.
|
|
Cancel request (internal call).
|
|
Called when the whole HTTP request has been sent out.
|
|
Redefines the building of the HTTP request.
|
|
Set user-defined opaque data, which can optionally be freed via `fn' if a non-NULL function pointer is given.
|
|
Get the state of the HTTP request.
|
|
|
|
Create a child request, to follow redirection transparently. All callbacks will be rerouted to the parent request, as if they came from the original parent.
|
|
Cancel request (system call error).
|
|
I/O callback invoked when we can write more data to the server to finish sending the HTTP request.
|
|
Allocate HTTP buffer, capable of holding data at `buf', of `len' bytes, and whose `written' bytes have already been sent out.
|
|
Dispose of HTTP buffer.
|
|
Shutdown the HTTP module.
|
|
Parses the content of a Content-Range header.
|
|
Called when data are available on the socket. Read them and pass them to http_got_data(). |
|
Extract HTTP version major/minor out of the given request, whose string length is `len' bytes.
|
|
Tell the user that we got new data for his request. If `eof' is TRUE, this is the last data we'll get. |
|
Called when the whole server's reply header was parsed.
|
|
Called when we start receiving the HTTP headers.
|
|
HTTP status callback. Add an X-Hostname line bearing the fully qualified hostname. |
|
Add a new http_range_t object within the sorted list. Refuse to add the range if it is overlapping existing ranges.
|
|
|
|
Checks whether range contains the contiguous [from, to] interval.
|
|
Free list of http_range_t objects.
|
|
|
|
Parse a Range: header in the request, returning the list of ranges that are enumerated. Invalid ranges are ignored. Only "bytes" ranges are supported. When parsing a "bytes=" style, it means it's a request, so we allow negative ranges. Otherwise, for "bytes " specifications, it's a reply and we ignore negative ranges. `size' gives the length of the resource, to resolve negative ranges and make sure we don't have ranges that extend past that size. The `field' and `vendor' arguments are only there to log errors, if any.
|
|
|
|
|
|
Redirect current HTTP request to some other URL.
|
|
Send HTTP status on socket, with code and reason. If `hev' is non-null, it points to a vector of http_extra_desc_t items, containing `hevcnt' entries. Each entry describes something to be inserted in the header. The connection is NOT closed physically. At the HTTP level, the connection is closed if an error is returned (either 4xx or 5xx) or a redirection occurs (3xx). Unless keep_alive = true. When the outgoing bandwidth is saturated, we start to limit the size of the generated headers. We reduce the size of the generated header to about 512 bytes, and remove non-essential things.
|
|
Parse protocol status line, and return the status code, and optionally a pointer within the string where the status message starts (if `msg' is a non-null pointer), and the protocol major/minor (if `major' and `minor' are non-null). If `proto' is non-null, then when there is a leading protocol string in the reply, it must be equal to `proto'.
We don't yet handle "SMTP-like continuations":
There is no way to return the value of "ZZZ" via this routine.
|
|
Interceptor callback for `data_ind' in child requests. Reroute to parent request. |
|
Interceptor callback for `error_ind' in child requests. Reroute to parent request. |
|
Interceptor callback for `header_ind' in child requests. Reroute to parent request. |
|
Called from main timer to expire HTTP requests that take too long.
|
|
Parse HTTP url and extract the IP/port we need to connect to. Also identifies the start of the path to request on the server.
|
|
|
|
|
|
Initial value: { "OK", "Invalid HTTP URL", "Connection failed", "I/O error", "Request too large", "Header too large", "User cancel", "Got EOF", "Unparseable HTTP status", "Got moved status, but no location", "Connection timeout", "Data timeout", "Nested redirection", "Invalid URI in Location header", "Connection was closed, all OK", "Redirected, following disabled", } |
|
Used to return error codes during setup.
|
|
Initial value: { err_line_too_long, NULL, err_header_error, err_input_exception, err_input_buffer_full, err_header_read_error, err_header_read_eof, NULL, } |
|
Error from http_url_parse().
|
|
Initial value: { "HEAD", "GET", "POST", } |
|
Initial value: { "OK", "Not an http URI", "More than one <user>:<password>", "Truncated <user>:<password>", "Could not parse port", "Port value is out of range", "Could not parse host", "Could not resolve host into IP", "URL has no URI part", } |
|
In order to allow detection of logically freed structures when we return from user callbacks, we delay the physical removal of the http_async structure to the clock timer. A freed structure is marked HA_F_FREED and its magic number is zeroed to prevent accidental reuse. All freed structures are enqueued in the sl_ha_freed list. |
|
To spot reply timeouts.
|