Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:33 2007

Asterisk developer's documentation :: Codename Pineapple


http.h File Reference


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.

#include "asterisk/config.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
struct  server_args
struct  server_instance
struct  SSL
struct  SSL_CTX
struct  tls_config

Defines

#define AST_CERTFILE   "asterisk.pem"

Typedefs

typedef ast_str *(* ast_http_callback )(struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
 HTTP Callbacks take the socket.

Functions

ast_strast_http_error (int status, const char *title, const char *extra_header, const char *text)
 Return an ast_str malloc()'d string containing an HTTP error message.
int ast_http_init (void)
int ast_http_reload (void)
int ast_http_uri_link (struct ast_http_uri *urihandler)
 Link into the Asterisk HTTP server.
void ast_http_uri_unlink (struct ast_http_uri *urihandler)
 Destroy an HTTP server.
void * server_root (void *)
void server_start (struct server_args *desc)
int ssl_setup (struct tls_config *cfg)


Define Documentation

#define AST_CERTFILE   "asterisk.pem"
 

SSL support

Definition at line 67 of file http.h.

Referenced by __ast_http_load(), and init_manager().


Typedef Documentation

typedef struct ast_str*(* ast_http_callback)(struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
 

HTTP Callbacks take the socket.

Note:
The method and the path as arguments and should return the content, allocated with malloc(). Status should be changed to reflect the status of the request if it isn't 200 and title may be set to a malloc()'d string to an appropriate title for non-200 responses. Content length may also be specified. The return value may include additional headers at the front and MUST include a blank line with
to provide separation between user headers and content (even if no content is specified)

Definition at line 148 of file http.h.


Function Documentation

struct ast_str* ast_http_error int  status,
const char *  title,
const char *  extra_header,
const char *  text
 

Return an ast_str malloc()'d string containing an HTTP error message.

Definition at line 262 of file http.c.

Referenced by handle_uri(), httpd_helper_thread(), and static_callback().

00263 {
00264    struct ast_str *out = ast_str_create(512);
00265    if (out == NULL)
00266       return out;
00267    ast_str_set(&out, 0,
00268       "Content-type: text/html\r\n"
00269       "%s"
00270       "\r\n"
00271       "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
00272       "<html><head>\r\n"
00273       "<title>%d %s</title>\r\n"
00274       "</head><body>\r\n"
00275       "<h1>%s</h1>\r\n"
00276       "<p>%s</p>\r\n"
00277       "<hr />\r\n"
00278       "<address>Asterisk Server</address>\r\n"
00279       "</body></html>\r\n",
00280          (extra_header ? extra_header : ""), status, title, title, text);
00281    return out;
00282 }

int ast_http_init void   ) 
 

Definition at line 1005 of file http.c.

References __ast_http_load(), ast_cli_register_multiple(), ast_http_uri_link(), cli_http, staticuri, and statusuri.

01006 {
01007    ast_http_uri_link(&statusuri);
01008    ast_http_uri_link(&staticuri);
01009    ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry));
01010    return __ast_http_load(0);
01011 }

int ast_http_reload void   ) 
 

Definition at line 990 of file http.c.

References __ast_http_load().

00991 {
00992    return __ast_http_load(1);
00993 }

int ast_http_uri_link struct ast_http_uri urih  ) 
 

Link into the Asterisk HTTP server.

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 293 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, len, and ast_http_uri::uri.

Referenced by ast_http_init().

00294 {
00295    struct ast_http_uri *uri;
00296    int len = strlen(urih->uri);
00297 
00298    AST_RWLIST_WRLOCK(&uris);
00299 
00300    if ( AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len ) {
00301       AST_RWLIST_INSERT_HEAD(&uris, urih, entry);
00302       AST_RWLIST_UNLOCK(&uris);
00303       return 0;
00304    }
00305 
00306    AST_RWLIST_TRAVERSE(&uris, uri, entry) {
00307       if ( AST_RWLIST_NEXT(uri, entry) 
00308          && strlen(AST_RWLIST_NEXT(uri, entry)->uri) <= len ) {
00309          AST_RWLIST_INSERT_AFTER(&uris, uri, urih, entry);
00310          AST_RWLIST_UNLOCK(&uris); 
00311          return 0;
00312       }
00313    }
00314 
00315    AST_RWLIST_INSERT_TAIL(&uris, urih, entry);
00316 
00317    AST_RWLIST_UNLOCK(&uris);
00318    
00319    return 0;
00320 }  

void ast_http_uri_unlink struct ast_http_uri urihandler  ) 
 

Destroy an HTTP server.

Definition at line 322 of file http.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

00323 {
00324    AST_RWLIST_WRLOCK(&uris);
00325    AST_RWLIST_REMOVE(&uris, urih, entry);
00326    AST_RWLIST_UNLOCK(&uris);
00327 }

void* server_root void *   ) 
 

Definition at line 642 of file http.c.

References ast_calloc, ast_log(), ast_pthread_create_background, ast_wait_for_input(), desc, free, LOG_WARNING, and make_file_from_fd().

00643 {
00644    struct server_args *desc = data;
00645    int fd;
00646    struct sockaddr_in sin;
00647    socklen_t sinlen;
00648    struct server_instance *ser;
00649    pthread_t launched;
00650    pthread_attr_t attr;
00651    
00652    for (;;) {
00653       int i, flags;
00654 
00655       if (desc->periodic_fn)
00656          desc->periodic_fn(desc);
00657       i = ast_wait_for_input(desc->accept_fd, desc->poll_timeout);
00658       if (i <= 0)
00659          continue;
00660       sinlen = sizeof(sin);
00661       fd = accept(desc->accept_fd, (struct sockaddr *)&sin, &sinlen);
00662       if (fd < 0) {
00663          if ((errno != EAGAIN) && (errno != EINTR))
00664             ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
00665          continue;
00666       }
00667       ser = ast_calloc(1, sizeof(*ser));
00668       if (!ser) {
00669          ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
00670          close(fd);
00671          continue;
00672       }
00673       flags = fcntl(fd, F_GETFL);
00674       fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
00675       ser->fd = fd;
00676       ser->parent = desc;
00677       memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
00678 
00679       pthread_attr_init(&attr);
00680       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00681          
00682       if (ast_pthread_create_background(&launched, &attr, make_file_from_fd, ser)) {
00683          ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
00684          close(ser->fd);
00685          free(ser);
00686       }
00687 
00688       pthread_attr_destroy(&attr);
00689    }
00690    return NULL;
00691 }

void server_start struct server_args desc  ) 
 

This is a generic (re)start routine for a TCP server, which does the socket/bind/listen and starts a thread for handling accept().

Definition at line 732 of file http.c.

References ast_inet_ntoa(), ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, desc, error(), LOG_DEBUG, LOG_NOTICE, LOG_WARNING, and option_debug.

00733 {
00734    int flags;
00735    int x = 1;
00736    
00737    /* Do nothing if nothing has changed */
00738    if (!memcmp(&desc->oldsin, &desc->sin, sizeof(desc->oldsin))) {
00739       if (option_debug)
00740          ast_log(LOG_DEBUG, "Nothing changed in %s\n", desc->name);
00741       return;
00742    }
00743    
00744    desc->oldsin = desc->sin;
00745    
00746    /* Shutdown a running server if there is one */
00747    if (desc->master != AST_PTHREADT_NULL) {
00748       pthread_cancel(desc->master);
00749       pthread_kill(desc->master, SIGURG);
00750       pthread_join(desc->master, NULL);
00751    }
00752    
00753    if (desc->accept_fd != -1)
00754       close(desc->accept_fd);
00755 
00756    /* If there's no new server, stop here */
00757    if (desc->sin.sin_family == 0)
00758       return;
00759 
00760    desc->accept_fd = socket(AF_INET, SOCK_STREAM, 0);
00761    if (desc->accept_fd < 0) {
00762       ast_log(LOG_WARNING, "Unable to allocate socket for %s: %s\n",
00763          desc->name, strerror(errno));
00764       return;
00765    }
00766    
00767    setsockopt(desc->accept_fd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
00768    if (bind(desc->accept_fd, (struct sockaddr *)&desc->sin, sizeof(desc->sin))) {
00769       ast_log(LOG_NOTICE, "Unable to bind %s to %s:%d: %s\n",
00770          desc->name,
00771          ast_inet_ntoa(desc->sin.sin_addr), ntohs(desc->sin.sin_port),
00772          strerror(errno));
00773       goto error;
00774    }
00775    if (listen(desc->accept_fd, 10)) {
00776       ast_log(LOG_NOTICE, "Unable to listen for %s!\n", desc->name);
00777       goto error;
00778    }
00779    flags = fcntl(desc->accept_fd, F_GETFL);
00780    fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK);
00781    if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
00782       ast_log(LOG_NOTICE, "Unable to launch %s on %s:%d: %s\n",
00783          desc->name,
00784          ast_inet_ntoa(desc->sin.sin_addr), ntohs(desc->sin.sin_port),
00785          strerror(errno));
00786       goto error;
00787    }
00788    return;
00789 
00790 error:
00791    close(desc->accept_fd);
00792    desc->accept_fd = -1;
00793 }

int ssl_setup struct tls_config cfg  ) 
 

Definition at line 693 of file http.c.

References ast_strlen_zero(), ast_verbose(), tls_config::certfile, tls_config::cipher, tls_config::enabled, and tls_config::ssl_ctx.

00694 {
00695 #ifndef DO_SSL
00696    cfg->enabled = 0;
00697    return 0;
00698 #else
00699    if (!cfg->enabled)
00700       return 0;
00701    SSL_load_error_strings();
00702    SSLeay_add_ssl_algorithms();
00703    cfg->ssl_ctx = SSL_CTX_new( SSLv23_server_method() );
00704    if (!ast_strlen_zero(cfg->certfile)) {
00705       if (SSL_CTX_use_certificate_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0 ||
00706           SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, cfg->certfile, SSL_FILETYPE_PEM) == 0 ||
00707           SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 ) {
00708          ast_verbose("ssl cert error <%s>", cfg->certfile);
00709          sleep(2);
00710          cfg->enabled = 0;
00711          return 0;
00712       }
00713    }
00714    if (!ast_strlen_zero(cfg->cipher)) {
00715       if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) {
00716          ast_verbose("ssl cipher error <%s>", cfg->cipher);
00717          sleep(2);
00718          cfg->enabled = 0;
00719          return 0;
00720       }
00721    }
00722    ast_verbose("ssl cert ok");
00723    return 1;
00724 #endif
00725 }


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen