Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

http.c File Reference


Detailed Description

HTTP routines.

The whole HTTP logic is not contained here. Only generic supporting routines are here.

Author:
Raphael Manfredi
Date:
2002-2003

#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_thttp_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_thttp_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_asynchttp_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


Define Documentation

#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.

#define HTTP_ASYNC_MAGIC   0xa91cf3eeU
 


Enumeration Type Documentation

enum http_reqtype
 

Enumeration values:
HTTP_HEAD 
HTTP_GET 
HTTP_POST 
NUM_HTTP_REQTYPES 


Function Documentation

void call_http_got_header gpointer  obj,
header_t header
[static]
 

Called when full header was collected.

gint code_message_parse const gchar *  line,
const gchar **  msg
[static]
 

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.

Returns:
status code, -1 on error.

void err_header_error gpointer  obj,
gint  error
[static]
 

void err_header_read_eof gpointer  obj  )  [static]
 

void err_header_read_error gpointer  obj,
gint  error
[static]
 

void err_input_buffer_full gpointer  obj  )  [static]
 

void err_input_exception gpointer  obj  )  [static]
 

void err_line_too_long gpointer  obj  )  [static]
 

void http_async_allow_redirects gpointer  handle,
gboolean  allow
 

Whether we should follow HTTP redirections (FALSE by default).

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
[static]
 

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.

Returns:
the length of the generated request, which must be terminated properly by a trailing "\r\n" on a line by itself to mark the end of the header.

void http_async_cancel gpointer  handle  ) 
 

Cancel request (user request).

void http_async_close gpointer  handle  ) 
 

Close request.

void http_async_connected gpointer  handle  ) 
 

Callback from the socket layer when the connection to the remote server is made.

struct 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
[static]
 

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.

Returns:
the newly created request, or NULL with `http_async_errno' set.

void http_async_error gpointer  handle,
gint  code
 

Cancel request (internal error).

void http_async_free struct http_async ha  )  [static]
 

Free the root of the HTTP asynchronous request handler, disposing of all its attached resources.

void http_async_free_pending void   )  [static]
 

Free all structures that have already been logically freed.

void http_async_free_recursive struct http_async ha  )  [static]
 

Free this HTTP asynchronous request handler, disposing of all its attached resources, recursively.

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.

Returns:
a handle on the request if OK, NULL on error with the http_async_errno variable set before returning.
When data is available, `data_ind' will be called. When all data have been read, a final call to `data_ind' is made with no data. If there is no `data_ind' routine, the connection will be closed after reading the whole header.

On error, `error_ind' will be called, and upon return, the request will be automatically cancelled.

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.

gpointer http_async_get_opaque gpointer  handle  ) 
 

Retrieve user-defined opaque data.

void http_async_headerr gpointer  handle,
gint  code
[static]
 

Cancel request (header parsing error).

void http_async_http_error gpointer  handle,
struct header header,
gint  code,
const gchar *  message
[static]
 

Cancel request (HTTP error).

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.

This can be used by client code to log request parameters.

Returns:
URL and fills `req' with the request type string (GET, POST, ...) if it is a non-NULL pointer, `path' with the request path, `addr' and `port' with the server address/port.

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 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.

The specified debugging level is explicitly given.

void http_async_newstate struct http_async ha,
http_state_t  state
[static]
 

Change the request state, and notify listener if any.

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_remove gpointer  handle,
http_errtype_t  type,
gpointer  code
[static]
 

Cancel request (internal call).

void http_async_request_sent struct http_async ha  )  [static]
 

Called when the whole HTTP request has been sent out.

void http_async_set_op_request gpointer  handle,
http_op_request_t  op
 

Redefines the building of the HTTP request.

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.

http_state_t http_async_state gpointer  handle  ) 
 

Get the state of the HTTP request.

const gchar* http_async_strerror guint  errnum  ) 
 

Returns:
human-readable error string corresponding to error code `errnum'.

gboolean http_async_subrequest struct http_async parent,
gchar *  url,
enum http_reqtype  type
[static]
 

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.

Returns:
whether we succeeded in creating the subrequest.

void http_async_syserr gpointer  handle,
gint  code
[static]
 

Cancel request (system call error).

void http_async_write_request gpointer  data,
gint  unused_source,
inputevt_cond_t  cond
[static]
 

I/O callback invoked when we can write more data to the server to finish sending the HTTP request.

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.

void http_close void   ) 
 

Shutdown the HTTP module.

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.

Parameters:
buf should point the payload of a Content-Range header
start will be set to the ``start'' offset
end will be set to the ``end'' offset
total will be set to the ``total'' size of the requested object.
Returns:
-1 on error, zero on success.

void http_data_read gpointer  data,
gint  unused_source,
inputevt_cond_t  cond
[static]
 

Called when data are available on the socket.

Read them and pass them to http_got_data().

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.

Returns:
TRUE when we identified the "HTTP/x.x" trailing string, filling major and minor accordingly.

void http_got_data struct http_async ha,
gboolean  eof
[static]
 

Tell the user that we got new data for his request.

If `eof' is TRUE, this is the last data we'll get.

void http_got_header struct http_async ha,
header_t header
[static]
 

Called when the whole server's reply header was parsed.

void http_header_start gpointer  handle  )  [static]
 

Called when we start receiving the HTTP headers.

void http_hostname_add gchar *  buf,
gint *  retval,
gpointer  unused_arg,
guint32  flags
 

HTTP status callback.

Add an X-Hostname line bearing the fully qualified hostname.

GSList* http_range_add GSList *  list,
filesize_t  start,
filesize_t  end,
const gchar *  field,
const gchar *  vendor,
gboolean *  ignored
[static]
 

Add a new http_range_t object within the sorted list.

Refuse to add the range if it is overlapping existing ranges.

Parameters:
`list' must be sorted if not NULL.
`start' the start of the range to add
`end' the end of the range to add
`field' arguments are only there to log errors, if any.
`vendor' is same as `field'.
`ignored' is set to TRUE if range was ignored.
Returns:
the new head of the list.

http_range_t* http_range_clone http_range_t range  )  [static]
 

Returns:
a new copy of the given HTTP range.

gboolean http_range_contains GSList *  ranges,
filesize_t  from,
filesize_t  to
 

Checks whether range contains the contiguous [from, to] interval.

void http_range_free GSList *  list  ) 
 

Free list of http_range_t objects.

GSList* http_range_merge GSList *  old_list,
GSList *  new_list
 

Returns:
a new list based on the merged ranges in the other lists given.

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.

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.

Returns:
a sorted list of http_range_t objects.

filesize_t http_range_size const GSList *  list  ) 
 

Returns:
total size of all the ranges.

const gchar* http_range_to_string const GSList *  list  ) 
 

Returns:
a pointer to static data, containing the available ranges.

void http_redirect struct http_async ha,
gchar *  url
[static]
 

Redirect current HTTP request to some other URL.

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.

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.

Returns:
TRUE if we were able to send everything, FALSE otherwise.

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).

If `proto' is non-null, then when there is a leading protocol string in the reply, it must be equal to `proto'.

Returns:
-1 if it fails to parse the status line correctly, the status code otherwise.
We recognize the following status lines:

  • ZZZ 403 message (major=0, minor=0)
  • ZZZ/2.3 403 message (major=2, minor=3)
  • 403 message (major=0, minor=0)

We don't yet handle "SMTP-like continuations":

  • 403-message line #1
  • 403-message line #2
  • 403 last message line

There is no way to return the value of "ZZZ" via this routine.

Attention:
NB: this routine is also used to parse GNUTELLA status codes, since they follow the same pattern as HTTP status codes.

void http_subreq_data_ind gpointer  handle,
gchar *  data,
gint  len
[static]
 

Interceptor callback for `data_ind' in child requests.

Reroute to parent request.

void http_subreq_error_ind gpointer  handle,
http_errtype_t  error,
gpointer  val
[static]
 

Interceptor callback for `error_ind' in child requests.

Reroute to parent request.

gboolean http_subreq_header_ind gpointer  handle,
struct header header,
gint  code,
const gchar *  message
[static]
 

Interceptor callback for `header_ind' in child requests.

Reroute to parent request.

void http_timer time_t  now  ) 
 

Called from main timer to expire HTTP requests that take too long.

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.

Also identifies the start of the path to request on the server.

Returns:
TRUE if the URL was correctly parsed, with `port', 'host' and `path' filled if they are non-NULL, FALSE otherwise. The variable `http_url_errno' is set accordingly.

const gchar* http_url_strerror http_url_error_t  errnum  ) 
 

Returns:
human-readable error string corresponding to error code `errnum'.

RCSID "$Id:http.  c,
v 1.46 2005/12/17 10:33:09 cbiere Exp $" 
 


Variable Documentation

const gchar* const error_str[] [static]
 

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",       
}

guint http_async_errno
 

Used to return error codes during setup.

struct io_error http_io_error [static]
 

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,
}

http_url_error_t http_url_errno
 

Error from http_url_parse().

const gchar* const http_verb[NUM_HTTP_REQTYPES] [static]
 

Initial value:

 {
    "HEAD",
    "GET",
    "POST",
}

gchar* parse_errstr[] [static]
 

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",              
}

GSList* sl_ha_freed = NULL [static]
 

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.

GSList* sl_outgoing = NULL [static]
 

To spot reply timeouts.


Generated on Sun Feb 12 10:50:03 2006 for Gtk-Gnutella by doxygen 1.3.6