Wed Apr 6 11:30:05 2011

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

References ast_http_methods_text, and ast_cfhttp_methods_text::text.

00133 {
00134    return ast_http_methods_text[method].text;
00135 }

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

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

00440 {
00441    struct ast_str *http_headers = ast_str_create(128);
00442    struct ast_str *out = ast_str_create(512);
00443 
00444    if (!http_headers || !out) {
00445       ast_free(http_headers);
00446       ast_free(out);
00447       return;
00448    }
00449 
00450    ast_str_set(&http_headers, 0,
00451       "WWW-authenticate: Digest algorithm=MD5, realm=\"%s\", nonce=\"%08lx\", qop=\"auth\", opaque=\"%08lx\"%s\r\n"
00452       "Content-type: text/html",
00453       realm ? realm : "Asterisk",
00454       nonce,
00455       opaque,
00456       stale ? ", stale=true" : "");
00457 
00458    ast_str_set(&out, 0,
00459       "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
00460       "<html><head>\r\n"
00461       "<title>401 Unauthorized</title>\r\n"
00462       "</head><body>\r\n"
00463       "<h1>401 Unauthorized</h1>\r\n"
00464       "<p>%s</p>\r\n"
00465       "<hr />\r\n"
00466       "<address>Asterisk Server</address>\r\n"
00467       "</body></html>\r\n",
00468       text ? text : "");
00469 
00470    ast_http_send(ser, AST_HTTP_UNKNOWN, 401, "Unauthorized", http_headers, out, 0, 0);
00471    return;
00472 }

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

00476 {
00477    struct ast_str *http_headers = ast_str_create(40);
00478    struct ast_str *out = ast_str_create(256);
00479 
00480    if (!http_headers || !out) {
00481       ast_free(http_headers);
00482       ast_free(out);
00483       return;
00484    }
00485 
00486    ast_str_set(&http_headers, 0, "Content-type: text/html");
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>%d %s</title>\r\n"
00492       "</head><body>\r\n"
00493       "<h1>%s</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          status_code, status_title, status_title, text);
00499 
00500    ast_http_send(ser, AST_HTTP_UNKNOWN, status_code, status_title, http_headers, out, 0, 0);
00501    return;
00502 }

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

References ARRAY_LEN, ext, and mimetypes.

Referenced by static_callback().

00138 {
00139    int x;
00140 
00141    if (ftype) {
00142       for (x = 0; x < ARRAY_LEN(mimetypes); x++) {
00143          if (!strcasecmp(ftype, mimetypes[x].ext)) {
00144             return mimetypes[x].mtype;
00145          }
00146       }
00147    }
00148    return NULL;
00149 }

struct ast_variable* ast_http_get_cookies ( struct ast_variable headers  ) 

Get cookie from Request headers.

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

00812 {
00813    struct ast_variable *v, *cookies=NULL;
00814 
00815    for (v = headers; v; v = v->next) {
00816       if (!strncasecmp(v->name, "Cookie", 6)) {
00817          char *tmp = ast_strdupa(v->value);
00818          if (cookies) {
00819             ast_variables_destroy(cookies);
00820          }
00821 
00822          cookies = parse_cookies(tmp);
00823       }
00824    }
00825    return cookies;
00826 }

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

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

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

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

00152 {
00153    uint32_t mngid = 0;
00154    struct ast_variable *v, *cookies;
00155 
00156    cookies = ast_http_get_cookies(headers);
00157    for (v = cookies; v; v = v->next) {
00158       if (!strcasecmp(v->name, "mansession_id")) {
00159          sscanf(v->value, "%30x", &mngid);
00160          break;
00161       }
00162    }
00163    if (cookies) {
00164       ast_variables_destroy(cookies);
00165    }
00166    return mngid;
00167 }

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

References ast_copy_string().

00170 {
00171    if (buf) {
00172       ast_copy_string(buf, prefix, len);
00173    }
00174 }

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 364 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, fwrite, len(), and LOG_WARNING.

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

00368 {
00369    struct timeval now = ast_tvnow();
00370    struct ast_tm tm;
00371    char timebuf[80];
00372    int content_length = 0;
00373 
00374    if (!ser || 0 == ser->f) {
00375       return;
00376    }
00377 
00378    ast_strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", ast_localtime(&now, &tm, "GMT"));
00379 
00380    /* calc conetnt length */
00381    if (out) {
00382       content_length += strlen(ast_str_buffer(out));
00383    }
00384 
00385    if (fd) {
00386       content_length += lseek(fd, 0, SEEK_END);
00387       lseek(fd, 0, SEEK_SET);
00388    }
00389 
00390    /* send http header */
00391    fprintf(ser->f, "HTTP/1.1 %d %s\r\n"
00392       "Server: Asterisk/%s\r\n"
00393       "Date: %s\r\n"
00394       "Connection: close\r\n"
00395       "%s"
00396       "Content-Length: %d\r\n"
00397       "%s\r\n\r\n",
00398       status_code, status_title ? status_title : "OK",
00399       ast_get_version(),
00400       timebuf,
00401       static_content ? "" : "Cache-Control: no-cache, no-store\r\n",
00402       content_length,
00403       http_header ? ast_str_buffer(http_header) : ""
00404       );
00405 
00406    /* send content */
00407    if (method != AST_HTTP_HEAD || status_code >= 400) {
00408       if (out) {
00409          fprintf(ser->f, "%s", ast_str_buffer(out));
00410       }
00411 
00412       if (fd) {
00413          char buf[256];
00414          int len;
00415          while ((len = read(fd, buf, sizeof(buf))) > 0) {
00416             if (fwrite(buf, len, 1, ser->f) != 1) {
00417                ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00418                break;
00419             }
00420          }
00421       }
00422    }
00423 
00424    if (http_header) {
00425       ast_free(http_header);
00426    }
00427    if (out) {
00428       ast_free(out);
00429    }
00430 
00431    fclose(ser->f);
00432    ser->f = 0;
00433    return;
00434 }

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

00514 {
00515    struct ast_http_uri *uri;
00516    int len = strlen(urih->uri);
00517 
00518    AST_RWLIST_WRLOCK(&uris);
00519 
00520    if ( AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len ) {
00521       AST_RWLIST_INSERT_HEAD(&uris, urih, entry);
00522       AST_RWLIST_UNLOCK(&uris);
00523       return 0;
00524    }
00525 
00526    AST_RWLIST_TRAVERSE(&uris, uri, entry) {
00527       if (AST_RWLIST_NEXT(uri, entry) &&
00528          strlen(AST_RWLIST_NEXT(uri, entry)->uri) <= len) {
00529          AST_RWLIST_INSERT_AFTER(&uris, uri, urih, entry);
00530          AST_RWLIST_UNLOCK(&uris);
00531 
00532          return 0;
00533       }
00534    }
00535 
00536    AST_RWLIST_INSERT_TAIL(&uris, urih, entry);
00537 
00538    AST_RWLIST_UNLOCK(&uris);
00539 
00540    return 0;
00541 }

void ast_http_uri_unlink ( struct ast_http_uri urihandler  ) 

Unregister a URI handler.

Definition at line 543 of file http.c.

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

Referenced by unload_module().

00544 {
00545    AST_RWLIST_WRLOCK(&uris);
00546    AST_RWLIST_REMOVE(&uris, urih, entry);
00547    AST_RWLIST_UNLOCK(&uris);
00548 }

void ast_http_uri_unlink_all_with_key ( const char *  key  ) 

Unregister all handlers with matching key.

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

00551 {
00552    struct ast_http_uri *urih;
00553    AST_RWLIST_WRLOCK(&uris);
00554    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&uris, urih, entry) {
00555       if (!strcmp(urih->key, key)) {
00556          AST_RWLIST_REMOVE_CURRENT(entry);
00557       }
00558       if (urih->dmallocd) {
00559          ast_free(urih->data);
00560       }
00561       if (urih->mallocd) {
00562          ast_free(urih);
00563       }
00564    }
00565    AST_RWLIST_TRAVERSE_SAFE_END;
00566    AST_RWLIST_UNLOCK(&uris);
00567 }


Generated on Wed Apr 6 11:30:05 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7