Fri Feb 10 06:36:35 2012

Asterisk developer's documentation


http.h File Reference

Support for Private Asterisk HTTP Servers. More...

#include "asterisk/config.h"
#include "asterisk/tcptls.h"
#include "asterisk/linkedlists.h"

Include dependency graph for http.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_http_uri
 Definition of a URI handler. More...

Typedefs

typedef int(* ast_http_callback )(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 HTTP Callbacks.

Enumerations

enum  ast_http_method {
  AST_HTTP_UNKNOWN = -1, AST_HTTP_GET = 0, AST_HTTP_POST, AST_HTTP_HEAD,
  AST_HTTP_PUT
}
 HTTP Request methods known by Asterisk. More...

Functions

const char * ast_get_http_method (enum ast_http_method method) attribute_pure
 Return http method name string.
void ast_http_auth (struct ast_tcptls_session_instance *ser, const char *realm, const unsigned long nonce, const unsigned long opaque, int stale, const char *text)
 Send http "401 Unauthorized" response and close socket.
void ast_http_error (struct ast_tcptls_session_instance *ser, int status, const char *title, const char *text)
 Send HTTP error message and close socket.
const char * ast_http_ftype2mtype (const char *ftype) attribute_pure
 Return mime type based on extension.
struct ast_variableast_http_get_cookies (struct ast_variable *headers)
 Get cookie from Request headers.
struct ast_variableast_http_get_post_vars (struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
 Get post variables from client Request Entity-Body, if content type is application/x-www-form-urlencoded.
uint32_t ast_http_manid_from_vars (struct ast_variable *headers) attribute_pure
 Return manager id, if exist, from request headers.
void ast_http_prefix (char *buf, int len)
 Return the current prefix.
void ast_http_send (struct ast_tcptls_session_instance *ser, enum ast_http_method method, int status_code, const char *status_title, struct ast_str *http_header, struct ast_str *out, const int fd, unsigned int static_content)
 Generic function for sending http/1.1 response.
int ast_http_uri_link (struct ast_http_uri *urihandler)
 Register a URI handler.
void ast_http_uri_unlink (struct ast_http_uri *urihandler)
 Unregister a URI handler.
void ast_http_uri_unlink_all_with_key (const char *key)
 Unregister all handlers with matching key.


Detailed Description

Support for Private Asterisk HTTP Servers.

Note:
Note: The Asterisk HTTP servers are extremely simple and minimal and only support the "GET" method.
Author:
Mark Spencer <markster@digium.com>
Note:
In order to have TLS/SSL support, we need the openssl libraries. Still we can decide whether or not to use them by commenting in or out the DO_SSL macro. TLS/SSL support is basically implemented by reading from a config file (currently http.conf) the names of the certificate and cipher to use, and then run ssl_setup() to create an appropriate SSL_CTX (ssl_ctx) If we support multiple domains, presumably we need to read multiple certificates. When we are requested to open a TLS socket, we run make_file_from_fd() on the socket, to do the necessary setup. At the moment the context's name is hardwired in the function, but we can certainly make it into an extra parameter to the function. We declare most of ssl support variables unconditionally, because their number is small and this simplifies the code.

: the ssl-support variables (ssl_ctx, do_ssl, certfile, cipher) and their setup should be moved to a more central place, e.g. asterisk.conf and the source files that processes it. Similarly, ssl_setup() should be run earlier in the startup process so modules have it available.

Definition in file http.h.


Typedef Documentation

typedef int(* ast_http_callback)(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)

HTTP Callbacks.

Note:
The callback function receives server instance, uri, http method, get method (if present in URI), and http headers as arguments and should use the ast_http_send() function for sending content allocated with ast_str and/or content from an opened file descriptor.
Status and status text should be sent as arguments to the ast_http_send() function to reflect the status of the request (200 or 304, for example). Content length is calculated by ast_http_send() automatically.

Static content may be indicated to the ast_http_send() function, to indicate that it may be cached.

 * The return value may include additional headers at the front and MUST
 * include a blank line with \r\n to provide separation between user headers
 * and content (even if no content is specified)
 * 

For an error response, the ast_http_error() function may be used.

Definition at line 88 of file http.h.


Enumeration Type Documentation

HTTP Request methods known by Asterisk.

Enumerator:
AST_HTTP_UNKNOWN  Unknown response
AST_HTTP_GET 
AST_HTTP_POST 
AST_HTTP_HEAD 
AST_HTTP_PUT  Not supported in Asterisk

Definition at line 56 of file http.h.

00056                      {
00057    AST_HTTP_UNKNOWN = -1,   /*!< Unknown response */
00058    AST_HTTP_GET = 0,
00059    AST_HTTP_POST,
00060    AST_HTTP_HEAD,
00061    AST_HTTP_PUT,            /*!< Not supported in Asterisk */
00062 };


Function Documentation

const char* ast_get_http_method ( enum ast_http_method  method  ) 

Return http method name string.

Since:
1.8

Definition at line 150 of file http.c.

References ARRAY_LEN, ast_http_methods_text, and ast_cfhttp_methods_text::text.

Referenced by auth_http_callback().

00151 {
00152    int x;
00153 
00154    for (x = 0; x < ARRAY_LEN(ast_http_methods_text); x++) {
00155       if (ast_http_methods_text[x].method == method) {
00156          return ast_http_methods_text[x].text;
00157       }
00158    }
00159 
00160    return NULL;
00161 }

void ast_http_auth ( struct ast_tcptls_session_instance ser,
const char *  realm,
const unsigned long  nonce,
const unsigned long  opaque,
int  stale,
const char *  text 
)

Send http "401 Unauthorized" response and close socket.

Definition at line 464 of file http.c.

References ast_free, ast_http_send(), AST_HTTP_UNKNOWN, ast_str_create(), and ast_str_set().

Referenced by auth_http_callback().

00467 {
00468    struct ast_str *http_headers = ast_str_create(128);
00469    struct ast_str *out = ast_str_create(512);
00470 
00471    if (!http_headers || !out) {
00472       ast_free(http_headers);
00473       ast_free(out);
00474       return;
00475    }
00476 
00477    ast_str_set(&http_headers, 0,
00478       "WWW-authenticate: Digest algorithm=MD5, realm=\"%s\", nonce=\"%08lx\", qop=\"auth\", opaque=\"%08lx\"%s\r\n"
00479       "Content-type: text/html\r\n",
00480       realm ? realm : "Asterisk",
00481       nonce,
00482       opaque,
00483       stale ? ", stale=true" : "");
00484 
00485    ast_str_set(&out, 0,
00486       "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
00487       "<html><head>\r\n"
00488       "<title>401 Unauthorized</title>\r\n"
00489       "</head><body>\r\n"
00490       "<h1>401 Unauthorized</h1>\r\n"
00491       "<p>%s</p>\r\n"
00492       "<hr />\r\n"
00493       "<address>Asterisk Server</address>\r\n"
00494       "</body></html>\r\n",
00495       text ? text : "");
00496 
00497    ast_http_send(ser, AST_HTTP_UNKNOWN, 401, "Unauthorized", http_headers, out, 0, 0);
00498    return;
00499 }

void ast_http_error ( struct ast_tcptls_session_instance ser,
int  status,
const char *  title,
const char *  text 
)

Send HTTP error message and close socket.

Definition at line 502 of file http.c.

References ast_free, ast_http_send(), AST_HTTP_UNKNOWN, ast_str_create(), and ast_str_set().

Referenced by auth_http_callback(), generic_http_callback(), handle_uri(), http_post_callback(), httpd_helper_thread(), httpstatus_callback(), phoneprov_callback(), and static_callback().

00503 {
00504    struct ast_str *http_headers = ast_str_create(40);
00505    struct ast_str *out = ast_str_create(256);
00506 
00507    if (!http_headers || !out) {
00508       ast_free(http_headers);
00509       ast_free(out);
00510       return;
00511    }
00512 
00513    ast_str_set(&http_headers, 0, "Content-type: text/html\r\n");
00514 
00515    ast_str_set(&out, 0,
00516       "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
00517       "<html><head>\r\n"
00518       "<title>%d %s</title>\r\n"
00519       "</head><body>\r\n"
00520       "<h1>%s</h1>\r\n"
00521       "<p>%s</p>\r\n"
00522       "<hr />\r\n"
00523       "<address>Asterisk Server</address>\r\n"
00524       "</body></html>\r\n",
00525          status_code, status_title, status_title, text);
00526 
00527    ast_http_send(ser, AST_HTTP_UNKNOWN, status_code, status_title, http_headers, out, 0, 0);
00528    return;
00529 }

const char* ast_http_ftype2mtype ( const char *  ftype  ) 

Return mime type based on extension.

Parameters:
ftype filename extension
Returns:
String containing associated MIME type
Since:
1.8

Definition at line 163 of file http.c.

References ARRAY_LEN, ext, and mimetypes.

Referenced by build_profile(), and static_callback().

00164 {
00165    int x;
00166 
00167    if (ftype) {
00168       for (x = 0; x < ARRAY_LEN(mimetypes); x++) {
00169          if (!strcasecmp(ftype, mimetypes[x].ext)) {
00170             return mimetypes[x].mtype;
00171          }
00172       }
00173    }
00174    return NULL;
00175 }

struct ast_variable* ast_http_get_cookies ( struct ast_variable headers  )  [read]

Get cookie from Request headers.

Definition at line 820 of file http.c.

References ast_strdupa, ast_variables_destroy(), ast_variable::name, ast_variable::next, parse_cookies(), and ast_variable::value.

Referenced by ast_http_manid_from_vars(), generic_http_callback(), http_post_callback(), and httpstatus_callback().

00821 {
00822    struct ast_variable *v, *cookies=NULL;
00823 
00824    for (v = headers; v; v = v->next) {
00825       if (!strncasecmp(v->name, "Cookie", 6)) {
00826          char *tmp = ast_strdupa(v->value);
00827          if (cookies) {
00828             ast_variables_destroy(cookies);
00829          }
00830 
00831          cookies = parse_cookies(tmp);
00832       }
00833    }
00834    return cookies;
00835 }

struct ast_variable* ast_http_get_post_vars ( struct ast_tcptls_session_instance ser,
struct ast_variable headers 
) [read]

Get post variables from client Request Entity-Body, if content type is application/x-www-form-urlencoded.

Parameters:
ser TCP/TLS session object
headers List of HTTP headers
Returns:
List of variables within the POST body
Note:
Since returned list is malloc'd, list should be free'd by the calling function
Since:
1.8

Definition at line 600 of file http.c.

References ast_uri_decode(), ast_uri_http_legacy, ast_variable_new(), ast_tcptls_session_instance::f, ast_variable::name, ast_variable::next, strsep(), ast_variable::value, and var.

Referenced by auth_http_callback(), and generic_http_callback().

00602 {
00603    int content_length = 0;
00604    struct ast_variable *v, *post_vars=NULL, *prev = NULL;
00605    char *buf, *var, *val;
00606 
00607    for (v = headers; v; v = v->next) {
00608       if (!strcasecmp(v->name, "Content-Type")) {
00609          if (strcasecmp(v->value, "application/x-www-form-urlencoded")) {
00610             return NULL;
00611          }
00612          break;
00613       }
00614    }
00615 
00616    for (v = headers; v; v = v->next) {
00617       if (!strcasecmp(v->name, "Content-Length")) {
00618          content_length = atoi(v->value) + 1;
00619          break;
00620       }
00621    }
00622 
00623    if (!content_length) {
00624       return NULL;
00625    }
00626 
00627    if (!(buf = alloca(content_length))) {
00628       return NULL;
00629    }
00630    if (!fgets(buf, content_length, ser->f)) {
00631       return NULL;
00632    }
00633 
00634    while ((val = strsep(&buf, "&"))) {
00635       var = strsep(&val, "=");
00636       if (val) {
00637          ast_uri_decode(val, ast_uri_http_legacy);
00638       } else  {
00639          val = "";
00640       }
00641       ast_uri_decode(var, ast_uri_http_legacy);
00642       if ((v = ast_variable_new(var, val, ""))) {
00643          if (post_vars) {
00644             prev->next = v;
00645          } else {
00646             post_vars = v;
00647          }
00648          prev = v;
00649       }
00650    }
00651    return post_vars;
00652 }

uint32_t ast_http_manid_from_vars ( struct ast_variable headers  ) 

Return manager id, if exist, from request headers.

Parameters:
headers List of HTTP headers
Returns:
32-bit associated manager session identifier
Since:
1.8

Definition at line 177 of file http.c.

References ast_http_get_cookies(), ast_variables_destroy(), ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by http_post_callback(), and static_callback().

00178 {
00179    uint32_t mngid = 0;
00180    struct ast_variable *v, *cookies;
00181 
00182    cookies = ast_http_get_cookies(headers);
00183    for (v = cookies; v; v = v->next) {
00184       if (!strcasecmp(v->name, "mansession_id")) {
00185          sscanf(v->value, "%30x", &mngid);
00186          break;
00187       }
00188    }
00189    if (cookies) {
00190       ast_variables_destroy(cookies);
00191    }
00192    return mngid;
00193 }

void ast_http_prefix ( char *  buf,
int  len 
)

Return the current prefix.

Parameters:
[out] buf destination buffer for previous
[in] len length of prefix to copy
Since:
1.6.1

Definition at line 195 of file http.c.

References ast_copy_string().

00196 {
00197    if (buf) {
00198       ast_copy_string(buf, prefix, len);
00199    }
00200 }

void ast_http_send ( struct ast_tcptls_session_instance ser,
enum ast_http_method  method,
int  status_code,
const char *  status_title,
struct ast_str http_header,
struct ast_str out,
const int  fd,
unsigned int  static_content 
)

Generic function for sending http/1.1 response.

Parameters:
ser TCP/TLS session object
method GET/POST/HEAD
status_code HTTP response code (200/401/403/404/500)
status_title English equivalent to the status_code parameter
http_header An ast_str object containing all headers
out An ast_str object containing the body of the response
fd If out is NULL, a file descriptor where the body of the response is held (otherwise -1)
static_content Zero if the content is dynamically generated and should not be cached; nonzero otherwise
Note:
Function determines the HTTP response header from status_code, status_header, and http_header.
Extra HTTP headers MUST be present only in the http_header argument. The argument "out" should contain only content of the response (no headers!).

HTTP content can be constructed from the argument "out", if it is not NULL; otherwise, the function will read content from FD.

This function calculates the content-length http header itself.

Both the http_header and out arguments will be freed by this function; however, if FD is open, it will remain open.

Since:
1.8

Definition at line 390 of file http.c.

References ast_free, ast_get_version(), AST_HTTP_HEAD, ast_localtime(), ast_log(), ast_str_buffer(), ast_strftime(), ast_tvnow(), errno, ast_tcptls_session_instance::f, len(), and LOG_WARNING.

Referenced by ast_http_auth(), ast_http_error(), auth_http_callback(), generic_http_callback(), handle_uri(), httpstatus_callback(), phoneprov_callback(), and static_callback().

00394 {
00395    struct timeval now = ast_tvnow();
00396    struct ast_tm tm;
00397    char timebuf[80];
00398    int content_length = 0;
00399 
00400    if (!ser || 0 == ser->f) {
00401       return;
00402    }
00403 
00404    ast_strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", ast_localtime(&now, &tm, "GMT"));
00405 
00406    /* calc content length */
00407    if (out) {
00408       content_length += strlen(ast_str_buffer(out));
00409    }
00410 
00411    if (fd) {
00412       content_length += lseek(fd, 0, SEEK_END);
00413       lseek(fd, 0, SEEK_SET);
00414    }
00415 
00416    /* send http header */
00417    fprintf(ser->f, "HTTP/1.1 %d %s\r\n"
00418       "Server: Asterisk/%s\r\n"
00419       "Date: %s\r\n"
00420       "Connection: close\r\n"
00421       "%s"
00422       "Content-Length: %d\r\n"
00423       "%s"
00424       "\r\n",
00425       status_code, status_title ? status_title : "OK",
00426       ast_get_version(),
00427       timebuf,
00428       static_content ? "" : "Cache-Control: no-cache, no-store\r\n",
00429       content_length,
00430       http_header ? ast_str_buffer(http_header) : ""
00431       );
00432 
00433    /* send content */
00434    if (method != AST_HTTP_HEAD || status_code >= 400) {
00435       if (out) {
00436          fprintf(ser->f, "%s", ast_str_buffer(out));
00437       }
00438 
00439       if (fd) {
00440          char buf[256];
00441          int len;
00442          while ((len = read(fd, buf, sizeof(buf))) > 0) {
00443             if (fwrite(buf, len, 1, ser->f) != 1) {
00444                ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00445                break;
00446             }
00447          }
00448       }
00449    }
00450 
00451    if (http_header) {
00452       ast_free(http_header);
00453    }
00454    if (out) {
00455       ast_free(out);
00456    }
00457 
00458    fclose(ser->f);
00459    ser->f = 0;
00460    return;
00461 }

int ast_http_uri_link ( struct ast_http_uri urih  ) 

Register a URI handler.

Register a URI handler.

They are sorted by length of the string, not alphabetically. Duplicate entries are not replaced, but the insertion order (using <= and not just <) makes sure that more recent insertions hide older ones. On a lookup, we just scan the list and stop at the first matching entry.

Definition at line 540 of file http.c.

References AST_RWLIST_EMPTY, AST_RWLIST_FIRST, AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_HEAD, AST_RWLIST_INSERT_TAIL, AST_RWLIST_NEXT, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, http_uri_redirect::entry, len(), and ast_http_uri::uri.

Referenced by __ast_http_post_load(), __init_manager(), ast_http_init(), and load_module().

00541 {
00542    struct ast_http_uri *uri;
00543    int len = strlen(urih->uri);
00544 
00545    AST_RWLIST_WRLOCK(&uris);
00546 
00547    if ( AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len ) {
00548       AST_RWLIST_INSERT_HEAD(&uris, urih, entry);
00549       AST_RWLIST_UNLOCK(&uris);
00550       return 0;
00551    }
00552 
00553    AST_RWLIST_TRAVERSE(&uris, uri, entry) {
00554       if (AST_RWLIST_NEXT(uri, entry) &&
00555          strlen(AST_RWLIST_NEXT(uri, entry)->uri) <= len) {
00556          AST_RWLIST_INSERT_AFTER(&uris, uri, urih, entry);
00557          AST_RWLIST_UNLOCK(&uris);
00558 
00559          return 0;
00560       }
00561    }
00562 
00563    AST_RWLIST_INSERT_TAIL(&uris, urih, entry);
00564 
00565    AST_RWLIST_UNLOCK(&uris);
00566 
00567    return 0;
00568 }

void ast_http_uri_unlink ( struct ast_http_uri urihandler  ) 

Unregister a URI handler.

Definition at line 570 of file http.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and http_uri_redirect::entry.

Referenced by __init_manager(), and unload_module().

00571 {
00572    AST_RWLIST_WRLOCK(&uris);
00573    AST_RWLIST_REMOVE(&uris, urih, entry);
00574    AST_RWLIST_UNLOCK(&uris);
00575 }

void ast_http_uri_unlink_all_with_key ( const char *  key  ) 

Unregister all handlers with matching key.

Definition at line 577 of file http.c.

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_http_uri::data, ast_http_uri::dmallocd, http_uri_redirect::entry, ast_http_uri::key, and ast_http_uri::mallocd.

Referenced by __ast_http_post_load(), and unload_module().

00578 {
00579    struct ast_http_uri *urih;
00580    AST_RWLIST_WRLOCK(&uris);
00581    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&uris, urih, entry) {
00582       if (!strcmp(urih->key, key)) {
00583          AST_RWLIST_REMOVE_CURRENT(entry);
00584       }
00585       if (urih->dmallocd) {
00586          ast_free(urih->data);
00587       }
00588       if (urih->mallocd) {
00589          ast_free(urih);
00590       }
00591    }
00592    AST_RWLIST_TRAVERSE_SAFE_END;
00593    AST_RWLIST_UNLOCK(&uris);
00594 }


Generated on Fri Feb 10 06:36:36 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6