Mon Mar 19 11:30:48 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"

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.
ast_variableast_http_get_cookies (struct ast_variable *headers)
 Get cookie from Request headers.
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

enum ast_http_method

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

References ARRAY_LEN, ast_http_methods_text, and ast_cfhttp_methods_text::text.

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

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

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

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

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

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

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

References ARRAY_LEN, ext, and mimetypes.

Referenced by static_callback().

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

struct ast_variable* ast_http_get_cookies ( struct ast_variable headers  ) 

Get cookie from Request headers.

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

00837 {
00838    struct ast_variable *v, *cookies=NULL;
00839 
00840    for (v = headers; v; v = v->next) {
00841       if (!strncasecmp(v->name, "Cookie", 6)) {
00842          char *tmp = ast_strdupa(v->value);
00843          if (cookies) {
00844             ast_variables_destroy(cookies);
00845          }
00846 
00847          cookies = parse_cookies(tmp);
00848       }
00849    }
00850    return cookies;
00851 }

struct ast_variable* ast_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.

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

References ast_variable::name, ast_variable::next, ast_variable::value, and var.

00618 {
00619    int content_length = 0;
00620    struct ast_variable *v, *post_vars=NULL, *prev = NULL;
00621    char *buf, *var, *val;
00622 
00623    for (v = headers; v; v = v->next) {
00624       if (!strcasecmp(v->name, "Content-Type")) {
00625          if (strcasecmp(v->value, "application/x-www-form-urlencoded")) {
00626             return NULL;
00627          }
00628          break;
00629       }
00630    }
00631 
00632    for (v = headers; v; v = v->next) {
00633       if (!strcasecmp(v->name, "Content-Length")) {
00634          content_length = atoi(v->value) + 1;
00635          break;
00636       }
00637    }
00638 
00639    if (!content_length) {
00640       return NULL;
00641    }
00642 
00643    if (!(buf = alloca(content_length))) {
00644       return NULL;
00645    }
00646    if (!fgets(buf, content_length, ser->f)) {
00647       return NULL;
00648    }
00649 
00650    while ((val = strsep(&buf, "&"))) {
00651       var = strsep(&val, "=");
00652       if (val) {
00653          http_decode(val);
00654       } else  {
00655          val = "";
00656       }
00657       http_decode(var);
00658       if ((v = ast_variable_new(var, val, ""))) {
00659          if (post_vars) {
00660             prev->next = v;
00661          } else {
00662             post_vars = v;
00663          }
00664          prev = v;
00665       }
00666    }
00667    return post_vars;
00668 }

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

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

Referenced by http_post_callback(), and static_callback().

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

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

References ast_copy_string().

00194 {
00195    if (buf) {
00196       ast_copy_string(buf, prefix, len);
00197    }
00198 }

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 388 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(), handle_uri(), httpstatus_callback(), and phoneprov_callback().

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

int ast_http_uri_link ( struct ast_http_uri urih  ) 

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 538 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, ast_http_uri::entry, len(), and ast_http_uri::uri.

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

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

void ast_http_uri_unlink ( struct ast_http_uri urihandler  ) 

Unregister a URI handler.

Definition at line 568 of file http.c.

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

Referenced by unload_module().

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

void ast_http_uri_unlink_all_with_key ( const char *  key  ) 

Unregister all handlers with matching key.

Definition at line 575 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, ast_http_uri::entry, ast_http_uri::key, and ast_http_uri::mallocd.

Referenced by __ast_http_post_load(), and unload_module().

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


Generated on Mon Mar 19 11:30:48 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7