Tue Aug 20 16:35:05 2013

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"

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 151 of file http.c.

References ARRAY_LEN, ast_http_methods_text, and ast_cfhttp_methods_text::text.

Referenced by auth_http_callback().

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

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

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

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

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

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 164 of file http.c.

References ARRAY_LEN, ext, and mimetypes.

Referenced by build_profile(), and static_callback().

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

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

Get cookie from Request headers.

Definition at line 860 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().

00861 {
00862    struct ast_variable *v, *cookies=NULL;
00863 
00864    for (v = headers; v; v = v->next) {
00865       if (!strncasecmp(v->name, "Cookie", 6)) {
00866          char *tmp = ast_strdupa(v->value);
00867          if (cookies) {
00868             ast_variables_destroy(cookies);
00869          }
00870 
00871          cookies = parse_cookies(tmp);
00872       }
00873    }
00874    return cookies;
00875 }

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 623 of file http.c.

References ast_free, AST_HTTP_POST, ast_http_send(), ast_log(), ast_malloc, ast_variable_new(), ast_tcptls_session_instance::f, http_decode(), LOG_WARNING, MAX_POST_CONTENT, ast_variable::name, ast_variable::next, ast_variable::value, and var.

Referenced by auth_http_callback(), and generic_http_callback().

00625 {
00626    int content_length = 0;
00627    struct ast_variable *v, *post_vars=NULL, *prev = NULL;
00628    char *buf, *var, *val;
00629    int res;
00630 
00631    for (v = headers; v; v = v->next) {
00632       if (!strcasecmp(v->name, "Content-Type")) {
00633          if (strcasecmp(v->value, "application/x-www-form-urlencoded")) {
00634             return NULL;
00635          }
00636          break;
00637       }
00638    }
00639 
00640    for (v = headers; v; v = v->next) {
00641       if (!strcasecmp(v->name, "Content-Length")) {
00642          content_length = atoi(v->value);
00643          break;
00644       }
00645    }
00646 
00647    if (content_length <= 0) {
00648       return NULL;
00649    }
00650 
00651    if (content_length > MAX_POST_CONTENT - 1) {
00652       ast_log(LOG_WARNING, "Excessively long HTTP content. %d is greater than our max of %d\n",
00653             content_length, MAX_POST_CONTENT);
00654       ast_http_send(ser, AST_HTTP_POST, 413, "Request Entity Too Large", NULL, NULL, 0, 0);
00655       return NULL;
00656    }
00657 
00658    buf = ast_malloc(content_length + 1);
00659    if (!buf) {
00660       return NULL;
00661    }
00662 
00663    res = fread(buf, 1, content_length, ser->f);
00664    if (res < content_length) {
00665       /* Error, distinguishable by ferror() or feof(), but neither
00666        * is good. */
00667       goto done;
00668    }
00669    buf[content_length] = '\0';
00670 
00671    while ((val = strsep(&buf, "&"))) {
00672       var = strsep(&val, "=");
00673       if (val) {
00674          http_decode(val);
00675       } else  {
00676          val = "";
00677       }
00678       http_decode(var);
00679       if ((v = ast_variable_new(var, val, ""))) {
00680          if (post_vars) {
00681             prev->next = v;
00682          } else {
00683             post_vars = v;
00684          }
00685          prev = v;
00686       }
00687    }
00688    
00689 done:
00690    ast_free(buf);
00691    return post_vars;
00692 }

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

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

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 196 of file http.c.

References ast_copy_string().

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

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 393 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(), ast_http_get_post_vars(), auth_http_callback(), generic_http_callback(), handle_uri(), httpstatus_callback(), phoneprov_callback(), and static_callback().

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

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

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

void ast_http_uri_unlink ( struct ast_http_uri urihandler  ) 

Unregister a URI handler.

Definition at line 573 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().

00574 {
00575    AST_RWLIST_WRLOCK(&uris);
00576    AST_RWLIST_REMOVE(&uris, urih, entry);
00577    AST_RWLIST_UNLOCK(&uris);
00578 }

void ast_http_uri_unlink_all_with_key ( const char *  key  ) 

Unregister all handlers with matching key.

Definition at line 580 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().

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


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1