Thu Sep 7 01:03:30 2017

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

References ARRAY_LEN, ast_http_methods_text, and ast_cfhttp_methods_text::text.

Referenced by auth_http_callback().

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

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

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

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

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

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

References ARRAY_LEN, ext, and mimetypes.

Referenced by build_profile(), and static_callback().

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

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

Get cookie from Request headers.

Definition at line 862 of file http.c.

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

00863 {
00864    struct ast_variable *v, *cookies = NULL;
00865 
00866    for (v = headers; v; v = v->next) {
00867       if (!strcasecmp(v->name, "Cookie")) {
00868          ast_variables_destroy(cookies);
00869          cookies = parse_cookies(v->value);
00870       }
00871    }
00872    return cookies;
00873 }

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

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

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

00181 {
00182    uint32_t mngid = 0;
00183    struct ast_variable *v, *cookies;
00184 
00185    cookies = ast_http_get_cookies(headers);
00186    for (v = cookies; v; v = v->next) {
00187       if (!strcasecmp(v->name, "mansession_id")) {
00188          sscanf(v->value, "%30x", &mngid);
00189          break;
00190       }
00191    }
00192    ast_variables_destroy(cookies);
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_str_strlen(), ast_strftime(), ast_tcptls_close_session_file(), ast_tvnow(), errno, ast_tcptls_session_instance::f, len(), LOG_ERROR, 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 += ast_str_strlen(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 && ast_str_strlen(out)) {
00439          if (fwrite(ast_str_buffer(out), ast_str_strlen(out), 1, ser->f) != 1) {
00440             ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
00441          }
00442       }
00443 
00444       if (fd) {
00445          char buf[256];
00446          int len;
00447          while ((len = read(fd, buf, sizeof(buf))) > 0) {
00448             if (fwrite(buf, len, 1, ser->f) != 1) {
00449                ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00450                break;
00451             }
00452          }
00453       }
00454    }
00455 
00456    if (http_header) {
00457       ast_free(http_header);
00458    }
00459    if (out) {
00460       ast_free(out);
00461    }
00462 
00463    ast_tcptls_close_session_file(ser);
00464    return;
00465 }

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

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

void ast_http_uri_unlink ( struct ast_http_uri urihandler  ) 

Unregister a URI handler.

Definition at line 574 of file http.c.

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

Referenced by __init_manager(), http_shutdown(), and unload_module().

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

void ast_http_uri_unlink_all_with_key ( const char *  key  ) 

Unregister all handlers with matching key.

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

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


Generated on 7 Sep 2017 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1