Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
http.c File Reference

http server for AMI access More...

#include "asterisk.h"
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <signal.h>
#include <fcntl.h>
#include "asterisk/paths.h"
#include "asterisk/cli.h"
#include "asterisk/tcptls.h"
#include "asterisk/http.h"
#include "asterisk/utils.h"
#include "asterisk/strings.h"
#include "asterisk/config.h"
#include "asterisk/stringfields.h"
#include "asterisk/ast_version.h"
#include "asterisk/manager.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
#include "asterisk/netsock2.h"
#include "asterisk/json.h"
Include dependency graph for http.c:

Go to the source code of this file.

Data Structures

struct  ast_cfhttp_methods_text
 
struct  http_uri_redirect
 
struct  http_worker_private_data
 
struct  uri_redirects
 
struct  uris
 

Macros

#define BASIC_LEN   6
 
#define BASIC_PREFIX   "Basic "
 
#define DEFAULT_PORT   8088
 
#define DEFAULT_RESPONSE_HEADER_LENGTH   512
 
#define DEFAULT_SESSION_INACTIVITY   30000
 
#define DEFAULT_SESSION_KEEP_ALIVE   15000
 
#define DEFAULT_SESSION_LIMIT   100
 
#define DEFAULT_TLS_PORT   8089
 
#define INITIAL_RESPONSE_BODY_BUFFER   1024
 
#define MAX_CONTENT_LENGTH   40960
 
#define MAX_HTTP_LINE_LENGTH   4096
 
#define MAX_HTTP_REQUEST_HEADERS   100
 
#define MAX_PREFIX   80
 
#define MAX_SERVER_NAME_LENGTH   128
 
#define MIN_INITIAL_REQUEST_TIMEOUT   10000
 

Enumerations

enum  http_private_flags { HTTP_FLAG_HAS_BODY = (1 << 0), HTTP_FLAG_BODY_READ = (1 << 1), HTTP_FLAG_CLOSE_ON_COMPLETION = (1 << 2) }
 

Functions

static int __ast_http_load (int reload)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static void add_redirect (const char *value)
 Add a new URI redirect The entries in the redirect list are sorted by length, just like the list of URI handlers. More...
 
const char * ast_get_http_method (enum ast_http_method method)
 Return http method name string. More...
 
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. More...
 
int ast_http_body_discard (struct ast_tcptls_session_instance *ser)
 Read and discard any unread HTTP request body. More...
 
void ast_http_body_read_status (struct ast_tcptls_session_instance *ser, int read_success)
 Update the body read success status. More...
 
void ast_http_create_response (struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, struct ast_str *http_header_data, const char *text)
 Creates and sends a formatted http response message. More...
 
void ast_http_error (struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
 Send HTTP error message and close socket. More...
 
const char * ast_http_ftype2mtype (const char *ftype)
 Return mime type based on extension. More...
 
struct ast_http_authast_http_get_auth (struct ast_variable *headers)
 Get HTTP authentication information from headers. More...
 
static char * ast_http_get_contents (int *return_length, struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
 Returns the contents (body) of the HTTP request. More...
 
struct ast_variableast_http_get_cookies (struct ast_variable *headers)
 Get cookie from Request headers. More...
 
struct ast_jsonast_http_get_json (struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
 Get JSON from client Request Entity-Body, if content type is application/json. More...
 
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. More...
 
int ast_http_header_match (const char *name, const char *expected_name, const char *value, const char *expected_value)
 Check if the header and value match (case insensitive) their associated expected values. More...
 
int ast_http_header_match_in (const char *name, const char *expected_name, const char *value, const char *expected_value)
 Check if the header name matches the expected header name. If so, then check to see if the value can be located in the expected value. More...
 
int ast_http_header_parse (char *buf, char **name, char **value)
 Parse a header into the given name/value strings. More...
 
uint32_t ast_http_manid_from_vars (struct ast_variable *headers)
 Return manager id, if exist, from request headers. More...
 
void ast_http_prefix (char *buf, int len)
 Return the current prefix. More...
 
void ast_http_request_close_on_completion (struct ast_tcptls_session_instance *ser)
 Request the HTTP connection be closed after this HTTP request. More...
 
int ast_http_response_status_line (const char *buf, const char *version, int code)
 Parse the http response status line. More...
 
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, int fd, unsigned int static_content)
 Generic function for sending HTTP/1.1 response. More...
 
int ast_http_uri_link (struct ast_http_uri *urih)
 Link the new uri into the list. More...
 
void ast_http_uri_unlink (struct ast_http_uri *urih)
 Unregister a URI handler. More...
 
void ast_http_uri_unlink_all_with_key (const char *key)
 Unregister all handlers with matching key. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static struct ast_http_authauth_create (const char *userid, const char *password)
 
static int chunked_atoh (const char *s, int len)
 
static int get_content_length (struct ast_variable *headers)
 Returns the value of the Content-Length header. More...
 
static char * get_content_type (struct ast_variable *headers)
 Retrieves the content type specified in the "Content-Type" header. More...
 
static const char * get_header (struct ast_variable *headers, const char *field_name)
 Retrieves the header with the given field name. More...
 
static const char * get_transfer_encoding (struct ast_variable *headers)
 Returns the value of the Transfer-Encoding header. More...
 
static char * handle_show_http (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int handle_uri (struct ast_tcptls_session_instance *ser, char *uri, enum ast_http_method method, struct ast_variable *headers)
 
static int http_body_check_chunk_sync (struct ast_tcptls_session_instance *ser)
 
static int http_body_discard_chunk_trailer_headers (struct ast_tcptls_session_instance *ser)
 
static int http_body_discard_contents (struct ast_tcptls_session_instance *ser, int length, const char *what_getting)
 
static int http_body_get_chunk_length (struct ast_tcptls_session_instance *ser)
 
static int http_body_read_contents (struct ast_tcptls_session_instance *ser, char *buf, int length, const char *what_getting)
 
static int http_check_connection_close (struct ast_variable *headers)
 
static int http_request_headers_get (struct ast_tcptls_session_instance *ser, struct ast_variable **headers)
 
static void http_request_tracking_init (struct http_worker_private_data *request)
 
static int http_request_tracking_setup (struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
 
static void * httpd_helper_thread (void *arg)
 
static int httpd_process_request (struct ast_tcptls_session_instance *ser)
 
static int httpstatus_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_vars, struct ast_variable *headers)
 
static int load_module (void)
 
static struct ast_variableparse_cookies (const char *cookies)
 
static int reload_module (void)
 
static void remove_excess_lws (char *s)
 
static int static_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_vars, struct ast_variable *headers)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Built-in HTTP Server" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
 
static const struct ast_cfhttp_methods_text ast_http_methods_text []
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_http []
 
static struct ast_tcptls_session_args http_desc
 
static char http_server_name [MAX_SERVER_NAME_LENGTH]
 
static struct ast_tls_config http_tls_cfg
 
static struct ast_tcptls_session_args https_desc
 
struct {
   const char *   ext
 
   const char *   mtype
 
mimetypes []
 Limit the kinds of files we're willing to serve up. More...
 
static char prefix [MAX_PREFIX]
 
static int session_count = 0
 
static int session_inactivity = DEFAULT_SESSION_INACTIVITY
 
static int session_keep_alive = DEFAULT_SESSION_KEEP_ALIVE
 
static int session_limit = DEFAULT_SESSION_LIMIT
 
static struct ast_http_uri static_uri
 
static int static_uri_enabled
 
static struct ast_http_uri status_uri
 
static int status_uri_enabled
 
static struct uri_redirects uri_redirects = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct uris uris = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 

Detailed Description

http server for AMI access

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

This program implements a tiny http server and was inspired by micro-httpd by Jef Poskanzer

GMime http://spruce.sourceforge.net/gmime/

AMI over HTTP support - AMI over the http protocol

Definition in file http.c.

Macro Definition Documentation

◆ BASIC_LEN

#define BASIC_LEN   6

strlen(BASIC_PREFIX)

Definition at line 1577 of file http.c.

Referenced by ast_http_get_auth().

◆ BASIC_PREFIX

#define BASIC_PREFIX   "Basic "

Definition at line 1576 of file http.c.

Referenced by ast_http_get_auth().

◆ DEFAULT_PORT

#define DEFAULT_PORT   8088

Definition at line 69 of file http.c.

Referenced by __ast_http_load().

◆ DEFAULT_RESPONSE_HEADER_LENGTH

#define DEFAULT_RESPONSE_HEADER_LENGTH   512

Max size for the http response header

Definition at line 81 of file http.c.

Referenced by ast_http_auth(), and ast_http_error().

◆ DEFAULT_SESSION_INACTIVITY

#define DEFAULT_SESSION_INACTIVITY   30000

(ms) Idle time waiting for data.

Definition at line 73 of file http.c.

Referenced by __ast_http_load().

◆ DEFAULT_SESSION_KEEP_ALIVE

#define DEFAULT_SESSION_KEEP_ALIVE   15000

(ms) Idle time between HTTP requests

Definition at line 77 of file http.c.

Referenced by __ast_http_load().

◆ DEFAULT_SESSION_LIMIT

#define DEFAULT_SESSION_LIMIT   100

Definition at line 71 of file http.c.

Referenced by __ast_http_load().

◆ DEFAULT_TLS_PORT

#define DEFAULT_TLS_PORT   8089

Definition at line 70 of file http.c.

Referenced by __ast_http_load().

◆ INITIAL_RESPONSE_BODY_BUFFER

#define INITIAL_RESPONSE_BODY_BUFFER   1024

Initial response body length.

Definition at line 92 of file http.c.

Referenced by ast_http_create_response().

◆ MAX_CONTENT_LENGTH

#define MAX_CONTENT_LENGTH   40960

Maximum application/json or application/x-www-form-urlencoded body content length.

Definition at line 85 of file http.c.

Referenced by ast_http_get_contents().

◆ MAX_HTTP_LINE_LENGTH

#define MAX_HTTP_LINE_LENGTH   4096

Maximum line length for HTTP requests.

Definition at line 99 of file http.c.

Referenced by http_body_discard_chunk_trailer_headers(), http_body_get_chunk_length(), http_request_headers_get(), and httpd_process_request().

◆ MAX_HTTP_REQUEST_HEADERS

#define MAX_HTTP_REQUEST_HEADERS   100

Limit the number of request headers in case the sender is being ridiculous.

Definition at line 1744 of file http.c.

Referenced by http_request_headers_get().

◆ MAX_PREFIX

#define MAX_PREFIX   80

Definition at line 68 of file http.c.

Referenced by __ast_http_load().

◆ MAX_SERVER_NAME_LENGTH

#define MAX_SERVER_NAME_LENGTH   128

Max size for the http server name

Definition at line 79 of file http.c.

Referenced by __ast_http_load(), ast_http_create_response(), and ast_http_send().

◆ MIN_INITIAL_REQUEST_TIMEOUT

#define MIN_INITIAL_REQUEST_TIMEOUT   10000

(ms) Min timeout for initial HTTP request to start coming in.

Definition at line 75 of file http.c.

Referenced by httpd_helper_thread().

Enumeration Type Documentation

◆ http_private_flags

Enumerator
HTTP_FLAG_HAS_BODY 

TRUE if the HTTP request has a body.

HTTP_FLAG_BODY_READ 

TRUE if the HTTP request body has been read.

HTTP_FLAG_CLOSE_ON_COMPLETION 

TRUE if the HTTP request must close when completed.

Definition at line 439 of file http.c.

439  {
440  /*! TRUE if the HTTP request has a body. */
441  HTTP_FLAG_HAS_BODY = (1 << 0),
442  /*! TRUE if the HTTP request body has been read. */
443  HTTP_FLAG_BODY_READ = (1 << 1),
444  /*! TRUE if the HTTP request must close when completed. */
446 };

Function Documentation

◆ __ast_http_load()

static int __ast_http_load ( int  reload)
static

Definition at line 2077 of file http.c.

References ast_tcptls_session_args::accept_fd, add_redirect(), AST_AF_UNSPEC, AST_CERTFILE, ast_config_destroy(), ast_config_load2(), ast_copy_string(), ast_free, ast_get_version(), ast_http_uri_link(), ast_http_uri_unlink(), ast_log, ast_parse_arg(), AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_set_flag, ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_resolve(), ast_sockaddr_set_port, ast_sockaddr_setnull(), ast_sockaddr_stringify(), AST_SSL_DISABLE_TLSV1, AST_SSL_SERVER_CIPHER_ORDER, ast_ssl_setup(), ast_strdup, ast_strlen_zero, ast_tcptls_server_start(), ast_tcptls_server_stop(), ast_tls_read_conf(), ast_true(), ast_variable_browse(), ast_verb, ast_tls_config::capath, ast_tls_config::certfile, ast_tls_config::cipher, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_PORT, DEFAULT_SESSION_INACTIVITY, DEFAULT_SESSION_KEEP_ALIVE, DEFAULT_SESSION_LIMIT, DEFAULT_TLS_PORT, ast_tls_config::enabled, enabled, ast_tls_config::flags, http_server_name, http_tls_cfg, ast_variable::lineno, ast_tcptls_session_args::local_address, LOG_WARNING, MAX_PREFIX, MAX_SERVER_NAME_LENGTH, ast_variable::name, ast_variable::next, NULL, PARSE_DEFAULT, PARSE_IN_RANGE, PARSE_INT32, PARSE_UINT32, prefix, ast_tls_config::pvtfile, RAII_VAR, session_inactivity, session_keep_alive, session_limit, static_uri_enabled, status_uri_enabled, ast_tcptls_session_args::tls_cfg, and ast_variable::value.

Referenced by load_module(), and reload_module().

2078 {
2079  struct ast_config *cfg;
2080  struct ast_variable *v;
2081  int enabled = 0;
2082  int new_static_uri_enabled = 0;
2083  int new_status_uri_enabled = 1; /* Default to enabled for BC */
2084  char newprefix[MAX_PREFIX] = "";
2085  char server_name[MAX_SERVER_NAME_LENGTH];
2086  struct http_uri_redirect *redirect;
2087  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2088  uint32_t bindport = DEFAULT_PORT;
2089  RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
2090  int num_addrs = 0;
2091  int http_tls_was_enabled = 0;
2092 
2093  cfg = ast_config_load2("http.conf", "http", config_flags);
2094  if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
2095  return 0;
2096  }
2097 
2098  /* Even if the http.conf hasn't been updated, the TLS certs/keys may have been */
2099  if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2102  }
2103  return 0;
2104  }
2105 
2106  http_tls_was_enabled = (reload && http_tls_cfg.enabled);
2107 
2108  http_tls_cfg.enabled = 0;
2109 
2112 
2115 
2118 
2119  /* Apply modern intermediate settings according to the Mozilla OpSec team as of July 30th, 2015 but disable TLSv1 */
2121 
2123  http_tls_cfg.cipher = ast_strdup("ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA");
2124 
2126  while ((redirect = AST_RWLIST_REMOVE_HEAD(&uri_redirects, entry))) {
2127  ast_free(redirect);
2128  }
2130 
2132 
2136 
2137  snprintf(server_name, sizeof(server_name), "Asterisk/%s", ast_get_version());
2138 
2139  v = ast_variable_browse(cfg, "general");
2140  for (; v; v = v->next) {
2141  /* read tls config options while preventing unsupported options from being set */
2142  if (strcasecmp(v->name, "tlscafile")
2143  && strcasecmp(v->name, "tlscapath")
2144  && strcasecmp(v->name, "tlscadir")
2145  && strcasecmp(v->name, "tlsverifyclient")
2146  && strcasecmp(v->name, "tlsdontverifyserver")
2147  && strcasecmp(v->name, "tlsclientmethod")
2148  && strcasecmp(v->name, "sslclientmethod")
2150  continue;
2151  }
2152 
2153  if (!strcasecmp(v->name, "servername")) {
2154  if (!ast_strlen_zero(v->value)) {
2155  ast_copy_string(server_name, v->value, sizeof(server_name));
2156  } else {
2157  server_name[0] = '\0';
2158  }
2159  } else if (!strcasecmp(v->name, "enabled")) {
2160  enabled = ast_true(v->value);
2161  } else if (!strcasecmp(v->name, "enablestatic") || !strcasecmp(v->name, "enable_static")) {
2162  new_static_uri_enabled = ast_true(v->value);
2163  } else if (!strcasecmp(v->name, "enable_status")) {
2164  new_status_uri_enabled = ast_true(v->value);
2165  } else if (!strcasecmp(v->name, "bindport")) {
2167  &bindport, DEFAULT_PORT, 0, 65535)) {
2168  ast_log(LOG_WARNING, "Invalid port %s specified. Using default port %" PRId32 "\n",
2169  v->value, DEFAULT_PORT);
2170  }
2171  } else if (!strcasecmp(v->name, "bindaddr")) {
2172  if (!(num_addrs = ast_sockaddr_resolve(&addrs, v->value, 0, AST_AF_UNSPEC))) {
2173  ast_log(LOG_WARNING, "Invalid bind address %s\n", v->value);
2174  }
2175  } else if (!strcasecmp(v->name, "prefix")) {
2176  if (!ast_strlen_zero(v->value)) {
2177  newprefix[0] = '/';
2178  ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
2179  } else {
2180  newprefix[0] = '\0';
2181  }
2182  } else if (!strcasecmp(v->name, "redirect")) {
2183  add_redirect(v->value);
2184  } else if (!strcasecmp(v->name, "sessionlimit")) {
2186  &session_limit, DEFAULT_SESSION_LIMIT, 1, INT_MAX)) {
2187  ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2188  v->name, v->value, v->lineno);
2189  }
2190  } else if (!strcasecmp(v->name, "session_inactivity")) {
2193  ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2194  v->name, v->value, v->lineno);
2195  }
2196  } else if (!strcasecmp(v->name, "session_keep_alive")) {
2197  if (sscanf(v->value, "%30d", &session_keep_alive) != 1
2198  || session_keep_alive < 0) {
2200  ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2201  v->name, v->value, v->lineno);
2202  }
2203  } else {
2204  ast_log(LOG_WARNING, "Ignoring unknown option '%s' in http.conf\n", v->name);
2205  }
2206  }
2207 
2208  ast_config_destroy(cfg);
2209 
2210  if (strcmp(prefix, newprefix)) {
2211  ast_copy_string(prefix, newprefix, sizeof(prefix));
2212  }
2213 
2214  ast_copy_string(http_server_name, server_name, sizeof(http_server_name));
2215 
2216  if (num_addrs && enabled) {
2217  int i;
2218  for (i = 0; i < num_addrs; ++i) {
2222  }
2224  if (http_desc.accept_fd == -1) {
2225  ast_log(LOG_WARNING, "Failed to start HTTP server for address %s\n", ast_sockaddr_stringify(&addrs[i]));
2227  } else {
2228  ast_verb(1, "Bound HTTP server to address %s\n", ast_sockaddr_stringify(&addrs[i]));
2229  break;
2230  }
2231  }
2232  /* When no specific TLS bindaddr is specified, we just use
2233  * the non-TLS bindaddress here.
2234  */
2237  /* Of course, we can't use the same port though.
2238  * Since no bind address was specified, we just use the
2239  * default TLS port
2240  */
2242  }
2243  }
2244  if (http_tls_was_enabled && !http_tls_cfg.enabled) {
2247  /* We can get here either because a TLS-specific address was specified
2248  * or because we copied the non-TLS address here. In the case where
2249  * we read an explicit address from the config, there may have been
2250  * no port specified, so we'll just use the default TLS port.
2251  */
2254  }
2257  }
2258  }
2259 
2260  if (static_uri_enabled && !new_static_uri_enabled) {
2262  } else if (!static_uri_enabled && new_static_uri_enabled) {
2264  }
2265 
2266  static_uri_enabled = new_static_uri_enabled;
2267 
2268  if (status_uri_enabled && !new_status_uri_enabled) {
2270  } else if (!status_uri_enabled && new_status_uri_enabled) {
2272  }
2273 
2274  status_uri_enabled = new_status_uri_enabled;
2275 
2276  return 0;
2277 }
struct ast_variable * next
char * pvtfile
Definition: tcptls.h:90
#define AST_CERTFILE
Definition: tcptls.h:62
void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
This is a generic (re)start routine for a TCP server, which does the socket/bind/listen and starts a ...
Definition: tcptls.c:685
int ast_ssl_setup(struct ast_tls_config *cfg)
Set up an SSL server.
Definition: tcptls.c:570
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
static int static_uri_enabled
Definition: http.c:142
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
Definition: netsock2.h:171
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Definition: version.c:16
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define DEFAULT_PORT
Definition: http.c:69
#define LOG_WARNING
Definition: logger.h:274
static int status_uri_enabled
Definition: http.c:143
#define CONFIG_STATUS_FILEINVALID
void ast_http_uri_unlink(struct ast_http_uri *urih)
Unregister a URI handler.
Definition: http.c:705
#define DEFAULT_TLS_PORT
Definition: http.c:70
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define DEFAULT_SESSION_LIMIT
Definition: http.c:71
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3154
Structure for variables, used for configurations and for channel variables.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define MAX_PREFIX
Definition: http.c:68
Socket address structure.
Definition: netsock2.h:97
#define ast_verb(level,...)
Definition: logger.h:463
#define DEFAULT_SESSION_KEEP_ALIVE
Definition: http.c:77
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:140
#define ast_strlen_zero(foo)
Definition: strings.h:52
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
#define MAX_SERVER_NAME_LENGTH
Definition: http.c:79
#define ast_log
Definition: astobj2.c:42
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
static struct ast_tls_config http_tls_cfg
Definition: http.c:111
static struct ast_tcptls_session_args http_desc
Definition: http.c:118
#define CONFIG_STATUS_FILEUNCHANGED
static char http_server_name[MAX_SERVER_NAME_LENGTH]
Definition: http.c:104
static void add_redirect(const char *value)
Add a new URI redirect The entries in the redirect list are sorted by length, just like the list of U...
Definition: http.c:2022
static int session_limit
Definition: http.c:106
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define ast_free(a)
Definition: astmm.h:182
static int reload(void)
Definition: cdr_mysql.c:741
static int session_inactivity
Definition: http.c:107
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *result,...)
The argument parsing routine.
Definition: main/config.c:3657
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:843
#define DEFAULT_SESSION_INACTIVITY
Definition: http.c:73
Structure used to handle boolean flags.
Definition: utils.h:199
char * certfile
Definition: tcptls.h:89
int ast_http_uri_link(struct ast_http_uri *urih)
Link the new uri into the list.
Definition: http.c:673
static struct ast_http_uri static_uri
Definition: http.c:430
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_args *tls_desc, const char *varname, const char *value)
Used to parse conf files containing tls/ssl options.
Definition: tcptls.c:875
struct ast_flags flags
Definition: tcptls.h:94
Definition: search.h:40
char * capath
Definition: tcptls.h:93
void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc)
Shutdown a running server if there is one.
Definition: tcptls.c:849
struct ast_tls_config * tls_cfg
Definition: tcptls.h:134
struct ast_sockaddr local_address
Definition: tcptls.h:130
static int session_keep_alive
Definition: http.c:108
static struct ast_tcptls_session_args https_desc
Definition: http.c:128
static struct ast_http_uri status_uri
Definition: http.c:421
char * cipher
Definition: tcptls.h:91
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
Definition: netsock2.c:280
static char prefix[MAX_PREFIX]
Definition: http.c:141
static int enabled
Definition: dnsmgr.c:91
int enabled
Definition: tcptls.h:88

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2388 of file http.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2388 of file http.c.

◆ add_redirect()

static void add_redirect ( const char *  value)
static

Add a new URI redirect The entries in the redirect list are sorted by length, just like the list of URI handlers.

Definition at line 2022 of file http.c.

References ast_calloc, ast_copy_string(), ast_log, 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_skip_blanks(), ast_strdupa, http_uri_redirect::dest, LOG_WARNING, strsep(), and http_uri_redirect::target.

Referenced by __ast_http_load().

2023 {
2024  char *target, *dest;
2025  struct http_uri_redirect *redirect, *cur;
2026  unsigned int target_len;
2027  unsigned int total_len;
2028  size_t dest_len;
2029 
2030  dest = ast_strdupa(value);
2031  dest = ast_skip_blanks(dest);
2032  target = strsep(&dest, " ");
2033  target = ast_skip_blanks(target);
2034  target = strsep(&target, " "); /* trim trailing whitespace */
2035 
2036  if (!dest) {
2037  ast_log(LOG_WARNING, "Invalid redirect '%s'\n", value);
2038  return;
2039  }
2040 
2041  target_len = strlen(target) + 1;
2042  dest_len = strlen(dest) + 1;
2043  total_len = sizeof(*redirect) + target_len + dest_len;
2044 
2045  if (!(redirect = ast_calloc(1, total_len))) {
2046  return;
2047  }
2048  redirect->dest = redirect->target + target_len;
2049  strcpy(redirect->target, target);
2050  ast_copy_string(redirect->dest, dest, dest_len);
2051 
2053 
2054  target_len--; /* So we can compare directly with strlen() */
2056  || strlen(AST_RWLIST_FIRST(&uri_redirects)->target) <= target_len ) {
2059 
2060  return;
2061  }
2062 
2064  if (AST_RWLIST_NEXT(cur, entry)
2065  && strlen(AST_RWLIST_NEXT(cur, entry)->target) <= target_len ) {
2066  AST_RWLIST_INSERT_AFTER(&uri_redirects, cur, redirect, entry);
2068  return;
2069  }
2070  }
2071 
2073 
2075 }
#define AST_RWLIST_NEXT
Definition: linkedlists.h:440
#define AST_RWLIST_INSERT_AFTER
Definition: linkedlists.h:701
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define LOG_WARNING
Definition: logger.h:274
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
char * dest
Definition: http.c:171
int value
Definition: syslog.c:37
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:717
#define ast_log
Definition: astobj2.c:42
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
char target[0]
Definition: http.c:172
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
Definition: search.h:40
#define AST_RWLIST_FIRST
Definition: linkedlists.h:422

◆ ast_get_http_method()

const char* ast_get_http_method ( enum ast_http_method  method)

Return http method name string.

Since
1.8

Definition at line 190 of file http.c.

References ARRAY_LEN, ast_http_methods_text, NULL, and ast_cfhttp_methods_text::text.

Referenced by add_allow_header(), ast_ari_invoke(), auth_http_callback(), and handle_options().

191 {
192  int x;
193 
194  for (x = 0; x < ARRAY_LEN(ast_http_methods_text); x++) {
195  if (ast_http_methods_text[x].method == method) {
196  return ast_http_methods_text[x].text;
197  }
198  }
199 
200  return NULL;
201 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
const char * text
Definition: http.c:179
#define NULL
Definition: resample.c:96
const char * method
Definition: res_pjsip.c:4335
static const struct ast_cfhttp_methods_text ast_http_methods_text[]

◆ ast_http_auth()

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

References ast_http_create_response(), ast_str_create, ast_str_set(), and DEFAULT_RESPONSE_HEADER_LENGTH.

Referenced by auth_http_callback().

625 {
626  int status_code = 401;
627  char *status_title = "Unauthorized";
628  struct ast_str *http_header_data = ast_str_create(DEFAULT_RESPONSE_HEADER_LENGTH);
629 
630  if (http_header_data) {
631  ast_str_set(&http_header_data,
632  0,
633  "WWW-authenticate: Digest algorithm=MD5, realm=\"%s\", nonce=\"%08lx\", qop=\"auth\", opaque=\"%08lx\"%s\r\n"
634  "Content-type: text/html\r\n",
635  realm ? realm : "Asterisk",
636  nonce,
637  opaque,
638  stale ? ", stale=true" : "");
639  }
640 
642  status_code,
643  status_title,
644  http_header_data,
645  text);
646 }
char * text
Definition: app_queue.c:1508
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void ast_http_create_response(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, struct ast_str *http_header_data, const char *text)
Creates and sends a formatted http response message.
Definition: http.c:567
#define DEFAULT_RESPONSE_HEADER_LENGTH
Definition: http.c:81
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ ast_http_body_discard()

int ast_http_body_discard ( struct ast_tcptls_session_instance ser)

Read and discard any unread HTTP request body.

Since
12.4.0
Parameters
serHTTP TCP/TLS session object.
Return values
0on success.
-1on error.

Definition at line 1120 of file http.c.

References ast_assert, ast_debug, ast_set_flag, ast_test_flag, http_worker_private_data::body_length, http_worker_private_data::flags, http_body_check_chunk_sync(), http_body_discard_chunk_trailer_headers(), http_body_discard_contents(), http_body_get_chunk_length(), HTTP_FLAG_BODY_READ, HTTP_FLAG_CLOSE_ON_COMPLETION, HTTP_FLAG_HAS_BODY, ast_tcptls_session_instance::private_data, and request().

Referenced by ast_http_send(), and ast_websocket_uri_cb().

1121 {
1123 
1124  request = ser->private_data;
1125  if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)
1126  || ast_test_flag(&request->flags, HTTP_FLAG_BODY_READ)) {
1127  /* No body to read or it has already been read. */
1128  return 0;
1129  }
1131 
1132  ast_debug(1, "HTTP discarding unused request body\n");
1133 
1134  ast_assert(request->body_length != 0);
1135  if (0 < request->body_length) {
1136  if (http_body_discard_contents(ser, request->body_length, "body")) {
1138  return -1;
1139  }
1140  return 0;
1141  }
1142 
1143  /* parse chunked-body */
1144  for (;;) {
1145  int length;
1146 
1147  length = http_body_get_chunk_length(ser);
1148  if (length < 0) {
1150  return -1;
1151  }
1152  if (length == 0) {
1153  /* parsed last-chunk */
1154  break;
1155  }
1156 
1157  if (http_body_discard_contents(ser, length, "chunk-data")
1158  || http_body_check_chunk_sync(ser)) {
1160  return -1;
1161  }
1162  }
1163 
1164  /* Read and discard any trailer entity-header lines. */
1167  return -1;
1168  }
1169  return 0;
1170 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ast_assert(a)
Definition: utils.h:695
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct ast_flags flags
Definition: http.c:453
static int http_body_get_chunk_length(struct ast_tcptls_session_instance *ser)
Definition: http.c:1041
static int request(void *obj)
Definition: chan_pjsip.c:2559
static int http_body_discard_chunk_trailer_headers(struct ast_tcptls_session_instance *ser)
Definition: http.c:1100
static int http_body_discard_contents(struct ast_tcptls_session_instance *ser, int length, const char *what_getting)
Definition: http.c:964
static int http_body_check_chunk_sync(struct ast_tcptls_session_instance *ser)
Definition: http.c:1069

◆ ast_http_body_read_status()

void ast_http_body_read_status ( struct ast_tcptls_session_instance ser,
int  read_success 
)

Update the body read success status.

Since
12.4.0
Parameters
serHTTP TCP/TLS session object.
read_successTRUE if body was read successfully.
Returns
Nothing

Definition at line 899 of file http.c.

References ast_set_flag, ast_test_flag, http_worker_private_data::flags, HTTP_FLAG_BODY_READ, HTTP_FLAG_CLOSE_ON_COMPLETION, HTTP_FLAG_HAS_BODY, ast_tcptls_session_instance::private_data, and request().

Referenced by http_post_callback().

900 {
902 
903  request = ser->private_data;
904  if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)
905  || ast_test_flag(&request->flags, HTTP_FLAG_BODY_READ)) {
906  /* No body to read. */
907  return;
908  }
910  if (!read_success) {
912  }
913 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
struct ast_flags flags
Definition: http.c:453
static int request(void *obj)
Definition: chan_pjsip.c:2559

◆ ast_http_create_response()

void ast_http_create_response ( struct ast_tcptls_session_instance ser,
int  status_code,
const char *  status_title,
struct ast_str http_header_data,
const char *  text 
)

Creates and sends a formatted http response message.

Parameters
serTCP/TLS session object
status_codeHTTP response code (200/401/403/404/500)
status_titleEnglish equivalent to the status_code parameter
http_header_dataThe formatted text to use in the http header
textAdditional informational text to use in the response
Note
Function constructs response headers from the status_code, status_title and http_header_data parameters.

The response body is created as HTML content, from the status_code, status_title, and the text parameters.

The http_header_data parameter will be freed as a result of calling function.

Since
13.2.0

Definition at line 567 of file http.c.

References ast_debug, ast_free, ast_http_send(), AST_HTTP_UNKNOWN, ast_str_buffer(), ast_str_create, ast_str_set(), ast_strlen_zero, ast_tcptls_close_session_file(), ast_xml_escape(), http_server_name, INITIAL_RESPONSE_BODY_BUFFER, MAX_SERVER_NAME_LENGTH, and out.

Referenced by ast_http_auth(), and ast_http_error().

569 {
570  char server_name[MAX_SERVER_NAME_LENGTH];
571  struct ast_str *server_address = ast_str_create(MAX_SERVER_NAME_LENGTH);
573 
574  if (!http_header_data || !server_address || !out) {
575  ast_free(http_header_data);
576  ast_free(server_address);
577  ast_free(out);
578  if (ser) {
579  ast_debug(1, "HTTP closing session. OOM.\n");
581  }
582  return;
583  }
584 
586  ast_xml_escape(http_server_name, server_name, sizeof(server_name));
587  ast_str_set(&server_address,
588  0,
589  "<address>%s</address>\r\n",
590  server_name);
591  }
592 
593  ast_str_set(&out,
594  0,
595  "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
596  "<html><head>\r\n"
597  "<title>%d %s</title>\r\n"
598  "</head><body>\r\n"
599  "<h1>%s</h1>\r\n"
600  "<p>%s</p>\r\n"
601  "<hr />\r\n"
602  "%s"
603  "</body></html>\r\n",
604  status_code,
605  status_title,
606  status_title,
607  text ? text : "",
608  ast_str_buffer(server_address));
609 
610  ast_free(server_address);
611 
612  ast_http_send(ser,
614  status_code,
615  status_title,
616  http_header_data,
617  out,
618  0,
619  0);
620 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define INITIAL_RESPONSE_BODY_BUFFER
Definition: http.c:92
char * text
Definition: app_queue.c:1508
int ast_xml_escape(const char *string, char *outbuf, size_t buflen)
Escape reserved characters for use in XML.
Definition: main/utils.c:718
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define MAX_SERVER_NAME_LENGTH
Definition: http.c:79
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static char http_server_name[MAX_SERVER_NAME_LENGTH]
Definition: http.c:104
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
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, int fd, unsigned int static_content)
Generic function for sending HTTP/1.1 response.
Definition: http.c:456
#define ast_free(a)
Definition: astmm.h:182
FILE * out
Definition: utils/frame.c:33
void ast_tcptls_close_session_file(struct ast_tcptls_session_instance *tcptls_session)
Closes a tcptls session instance&#39;s file and/or file descriptor. The tcptls_session will be set to NUL...
Definition: tcptls.c:839
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ ast_http_error()

void ast_http_error ( struct ast_tcptls_session_instance ser,
int  status_code,
const char *  status_title,
const char *  text 
)

Send HTTP error message and close socket.

Definition at line 648 of file http.c.

References ast_http_create_response(), ast_str_create, ast_str_set(), and DEFAULT_RESPONSE_HEADER_LENGTH.

Referenced by ast_ari_callback(), ast_ari_events_event_websocket_ws_attempted_cb(), ast_websocket_uri_cb(), auth_http_callback(), event_session_allocation_error_handler(), generic_http_callback(), handle_uri(), http_callback(), http_post_callback(), http_request_headers_get(), http_request_tracking_setup(), httpd_helper_thread(), httpd_process_request(), httpstatus_callback(), static_callback(), and websocket_bad_request().

650 {
651  struct ast_str *http_header_data = ast_str_create(DEFAULT_RESPONSE_HEADER_LENGTH);
652 
653  if (http_header_data) {
654  ast_str_set(&http_header_data, 0, "Content-type: text/html\r\n");
655  }
656 
658  status_code,
659  status_title,
660  http_header_data,
661  text);
662 }
char * text
Definition: app_queue.c:1508
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void ast_http_create_response(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, struct ast_str *http_header_data, const char *text)
Creates and sends a formatted http response message.
Definition: http.c:567
#define DEFAULT_RESPONSE_HEADER_LENGTH
Definition: http.c:81
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ ast_http_ftype2mtype()

const char* ast_http_ftype2mtype ( const char *  ftype)

Return mime type based on extension.

Parameters
ftypefilename extension
Returns
String containing associated MIME type
Since
1.8

Definition at line 203 of file http.c.

References ARRAY_LEN, ext, mimetypes, and NULL.

Referenced by build_profile(), and static_callback().

204 {
205  int x;
206 
207  if (ftype) {
208  for (x = 0; x < ARRAY_LEN(mimetypes); x++) {
209  if (!strcasecmp(ftype, mimetypes[x].ext)) {
210  return mimetypes[x].mtype;
211  }
212  }
213  }
214  return NULL;
215 }
static struct @395 mimetypes[]
Limit the kinds of files we&#39;re willing to serve up.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define NULL
Definition: resample.c:96
const char * ext
Definition: http.c:147

◆ ast_http_get_auth()

struct ast_http_auth* ast_http_get_auth ( struct ast_variable headers)

Get HTTP authentication information from headers.

The returned object is AO2 managed, so clean up with ao2_cleanup().

Parameters
headersHTTP request headers.
Returns
HTTP auth structure.
NULL if no supported HTTP auth headers present.
Since
12

Definition at line 1579 of file http.c.

References ast_assert, ast_base64decode(), ast_begins_with(), ast_log, auth_create(), base64, BASIC_LEN, BASIC_PREFIX, LOG_DEBUG, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, password, strsep(), and ast_variable::value.

Referenced by authenticate_user(), and http_callback().

1580 {
1581  struct ast_variable *v;
1582 
1583  for (v = headers; v; v = v->next) {
1584  const char *base64;
1585  char decoded[256] = {};
1586  char *username;
1587  char *password;
1588 #ifdef AST_DEVMODE
1589  int cnt;
1590 #endif /* AST_DEVMODE */
1591 
1592  if (strcasecmp("Authorization", v->name) != 0) {
1593  continue;
1594  }
1595 
1596  if (!ast_begins_with(v->value, BASIC_PREFIX)) {
1598  "Unsupported Authorization scheme\n");
1599  continue;
1600  }
1601 
1602  /* Basic auth header parsing. RFC 2617, section 2.
1603  * credentials = "Basic" basic-credentials
1604  * basic-credentials = base64-user-pass
1605  * base64-user-pass = <base64 encoding of user-pass,
1606  * except not limited to 76 char/line>
1607  * user-pass = userid ":" password
1608  */
1609 
1610  base64 = v->value + BASIC_LEN;
1611 
1612  /* This will truncate "userid:password" lines to
1613  * sizeof(decoded). The array is long enough that this shouldn't
1614  * be a problem */
1615 #ifdef AST_DEVMODE
1616  cnt =
1617 #endif /* AST_DEVMODE */
1618  ast_base64decode((unsigned char*)decoded, base64,
1619  sizeof(decoded) - 1);
1620  ast_assert(cnt < sizeof(decoded));
1621 
1622  /* Split the string at the colon */
1623  password = decoded;
1624  username = strsep(&password, ":");
1625  if (!password) {
1626  ast_log(LOG_WARNING, "Invalid Authorization header\n");
1627  return NULL;
1628  }
1629 
1630  return auth_create(username, password);
1631  }
1632 
1633  return NULL;
1634 }
struct ast_variable * next
#define LOG_WARNING
Definition: logger.h:274
Structure for variables, used for configurations and for channel variables.
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define LOG_DEBUG
Definition: logger.h:241
static struct ast_str * password
Definition: cdr_mysql.c:77
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
Definition: main/utils.c:294
#define ast_log
Definition: astobj2.c:42
#define BASIC_LEN
Definition: http.c:1577
static struct ast_http_auth * auth_create(const char *userid, const char *password)
Definition: http.c:1545
char * strsep(char **str, const char *delims)
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Definition: strings.h:94
#define BASIC_PREFIX
Definition: http.c:1576
static char base64[64]
Definition: main/utils.c:78

◆ ast_http_get_contents()

static char* ast_http_get_contents ( int *  return_length,
struct ast_tcptls_session_instance ser,
struct ast_variable headers 
)
static

Returns the contents (body) of the HTTP request.

Parameters
return_lengthptr to int that returns content length
serHTTP TCP/TLS session object
headersList of HTTP headers
Returns
ptr to content (zero terminated) or NULL on failure
Note
Since returned ptr is malloc'd, it should be free'd by caller

Definition at line 1181 of file http.c.

References ast_assert, ast_debug, ast_free, ast_log, ast_malloc, ast_realloc, ast_set_flag, ast_test_flag, http_worker_private_data::body_length, buf, errno, http_worker_private_data::flags, http_body_check_chunk_sync(), http_body_discard_chunk_trailer_headers(), http_body_get_chunk_length(), http_body_read_contents(), HTTP_FLAG_BODY_READ, HTTP_FLAG_CLOSE_ON_COMPLETION, HTTP_FLAG_HAS_BODY, LOG_WARNING, MAX_CONTENT_LENGTH, NULL, ast_tcptls_session_instance::private_data, and request().

Referenced by ast_http_get_json(), and ast_http_get_post_vars().

1183 {
1185  int content_length;
1186  int bufsize;
1187  char *buf;
1188 
1189  request = ser->private_data;
1190  if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)) {
1191  /* no content - not an error */
1192  return NULL;
1193  }
1194  if (ast_test_flag(&request->flags, HTTP_FLAG_BODY_READ)) {
1195  /* Already read the body. Cannot read again. Assume no content. */
1196  ast_assert(0);
1197  return NULL;
1198  }
1200 
1201  ast_debug(2, "HTTP consuming request body\n");
1202 
1203  ast_assert(request->body_length != 0);
1204  if (0 < request->body_length) {
1205  /* handle regular non-chunked content */
1206  content_length = request->body_length;
1207  if (content_length > MAX_CONTENT_LENGTH) {
1208  ast_log(LOG_WARNING, "Excessively long HTTP content. (%d > %d)\n",
1209  content_length, MAX_CONTENT_LENGTH);
1211  errno = EFBIG;
1212  return NULL;
1213  }
1214  buf = ast_malloc(content_length + 1);
1215  if (!buf) {
1216  /* Malloc sets ENOMEM */
1218  return NULL;
1219  }
1220 
1221  if (http_body_read_contents(ser, buf, content_length, "body")) {
1223  errno = EIO;
1224  ast_free(buf);
1225  return NULL;
1226  }
1227 
1228  buf[content_length] = 0;
1229  *return_length = content_length;
1230  return buf;
1231  }
1232 
1233  /* pre-allocate buffer */
1234  bufsize = 250;
1235  buf = ast_malloc(bufsize);
1236  if (!buf) {
1238  return NULL;
1239  }
1240 
1241  /* parse chunked-body */
1242  content_length = 0;
1243  for (;;) {
1244  int chunk_length;
1245 
1246  chunk_length = http_body_get_chunk_length(ser);
1247  if (chunk_length < 0) {
1249  errno = EIO;
1250  ast_free(buf);
1251  return NULL;
1252  }
1253  if (chunk_length == 0) {
1254  /* parsed last-chunk */
1255  break;
1256  }
1257  if (content_length + chunk_length > MAX_CONTENT_LENGTH) {
1259  "Excessively long HTTP accumulated chunked body. (%d + %d > %d)\n",
1260  content_length, chunk_length, MAX_CONTENT_LENGTH);
1262  errno = EFBIG;
1263  ast_free(buf);
1264  return NULL;
1265  }
1266 
1267  /* insure buffer is large enough +1 */
1268  if (content_length + chunk_length >= bufsize) {
1269  char *new_buf;
1270 
1271  /* Increase bufsize until it can handle the expected data. */
1272  do {
1273  bufsize *= 2;
1274  } while (content_length + chunk_length >= bufsize);
1275 
1276  new_buf = ast_realloc(buf, bufsize);
1277  if (!new_buf) {
1279  ast_free(buf);
1280  return NULL;
1281  }
1282  buf = new_buf;
1283  }
1284 
1285  if (http_body_read_contents(ser, buf + content_length, chunk_length, "chunk-data")
1286  || http_body_check_chunk_sync(ser)) {
1288  errno = EIO;
1289  ast_free(buf);
1290  return NULL;
1291  }
1292  content_length += chunk_length;
1293  }
1294 
1295  /*
1296  * Read and discard any trailer entity-header lines
1297  * which we don't care about.
1298  *
1299  * XXX In the future we may need to add the trailer headers
1300  * to the passed in headers list rather than discarding them.
1301  */
1304  errno = EIO;
1305  ast_free(buf);
1306  return NULL;
1307  }
1308 
1309  buf[content_length] = 0;
1310  *return_length = content_length;
1311  return buf;
1312 }
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:228
#define ast_test_flag(p, flag)
Definition: utils.h:63
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:274
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static int http_body_read_contents(struct ast_tcptls_session_instance *ser, char *buf, int length, const char *what_getting)
Definition: http.c:928
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
struct ast_flags flags
Definition: http.c:453
int errno
#define ast_free(a)
Definition: astmm.h:182
static int http_body_get_chunk_length(struct ast_tcptls_session_instance *ser)
Definition: http.c:1041
static int request(void *obj)
Definition: chan_pjsip.c:2559
static int http_body_discard_chunk_trailer_headers(struct ast_tcptls_session_instance *ser)
Definition: http.c:1100
#define MAX_CONTENT_LENGTH
Definition: http.c:85
static int http_body_check_chunk_sync(struct ast_tcptls_session_instance *ser)
Definition: http.c:1069

◆ ast_http_get_cookies()

struct ast_variable* ast_http_get_cookies ( struct ast_variable headers)

Get cookie from Request headers.

Definition at line 1532 of file http.c.

References ast_variables_destroy(), ast_variable::name, ast_variable::next, NULL, parse_cookies(), and ast_variable::value.

Referenced by ast_http_manid_from_vars(), and httpstatus_callback().

1533 {
1534  struct ast_variable *v, *cookies = NULL;
1535 
1536  for (v = headers; v; v = v->next) {
1537  if (!strcasecmp(v->name, "Cookie")) {
1538  ast_variables_destroy(cookies);
1539  cookies = parse_cookies(v->value);
1540  }
1541  }
1542  return cookies;
1543 }
struct ast_variable * next
static struct ast_variable * parse_cookies(const char *cookies)
Definition: http.c:1498
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
Structure for variables, used for configurations and for channel variables.
#define NULL
Definition: resample.c:96

◆ ast_http_get_json()

struct ast_json* ast_http_get_json ( struct ast_tcptls_session_instance ser,
struct ast_variable headers 
)

Get JSON from client Request Entity-Body, if content type is application/json.

Parameters
serTCP/TLS session object
headersList of HTTP headers
Returns
Parsed JSON content body
NULL on error, if no content, or if different content type.
Since
12

Definition at line 1314 of file http.c.

References ast_free, ast_http_get_contents(), ast_json_load_buf(), ast_strlen_zero, buf, errno, get_content_type(), NULL, RAII_VAR, and type.

Referenced by ast_ari_callback().

1316 {
1317  int content_length = 0;
1318  struct ast_json *body;
1319  RAII_VAR(char *, buf, NULL, ast_free);
1320  RAII_VAR(char *, type, get_content_type(headers), ast_free);
1321 
1322  /* Use errno to distinguish errors from no body */
1323  errno = 0;
1324 
1325  if (ast_strlen_zero(type) || strcasecmp(type, "application/json")) {
1326  /* Content type is not JSON. Don't read the body. */
1327  return NULL;
1328  }
1329 
1330  buf = ast_http_get_contents(&content_length, ser, headers);
1331  if (!buf || !content_length) {
1332  /*
1333  * errno already set
1334  * or it is not an error to have zero content
1335  */
1336  return NULL;
1337  }
1338 
1339  body = ast_json_load_buf(buf, content_length, NULL);
1340  if (!body) {
1341  /* Failed to parse JSON; treat as an I/O error */
1342  errno = EIO;
1343  return NULL;
1344  }
1345 
1346  return body;
1347 }
static const char type[]
Definition: chan_ooh323.c:109
static char * ast_http_get_contents(int *return_length, struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
Returns the contents (body) of the HTTP request.
Definition: http.c:1181
struct ast_json * ast_json_load_buf(const char *buffer, size_t buflen, struct ast_json_error *error)
Parse buffer with known length into a JSON object or array.
Definition: json.c:564
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static char * get_content_type(struct ast_variable *headers)
Retrieves the content type specified in the "Content-Type" header.
Definition: http.c:761
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
int errno
#define ast_free(a)
Definition: astmm.h:182
Abstract JSON element (object, array, string, int, ...).

◆ ast_http_get_post_vars()

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
serTCP/TLS session object
headersList 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 1353 of file http.c.

References ast_free, ast_http_get_contents(), ast_strlen_zero, ast_uri_decode(), ast_uri_http_legacy, ast_variable_new, buf, errno, get_content_type(), NULL, RAII_VAR, strsep(), type, and var.

Referenced by ast_ari_callback(), auth_http_callback(), and generic_http_callback().

1355 {
1356  int content_length = 0;
1357  struct ast_variable *v, *post_vars=NULL, *prev = NULL;
1358  char *var, *val;
1359  RAII_VAR(char *, buf, NULL, ast_free);
1360  RAII_VAR(char *, type, get_content_type(headers), ast_free);
1361 
1362  /* Use errno to distinguish errors from no params */
1363  errno = 0;
1364 
1365  if (ast_strlen_zero(type) ||
1366  strcasecmp(type, "application/x-www-form-urlencoded")) {
1367  /* Content type is not form data. Don't read the body. */
1368  return NULL;
1369  }
1370 
1371  buf = ast_http_get_contents(&content_length, ser, headers);
1372  if (!buf || !content_length) {
1373  /*
1374  * errno already set
1375  * or it is not an error to have zero content
1376  */
1377  return NULL;
1378  }
1379 
1380  while ((val = strsep(&buf, "&"))) {
1381  var = strsep(&val, "=");
1382  if (val) {
1384  } else {
1385  val = "";
1386  }
1388  if ((v = ast_variable_new(var, val, ""))) {
1389  if (post_vars) {
1390  prev->next = v;
1391  } else {
1392  post_vars = v;
1393  }
1394  prev = v;
1395  }
1396  }
1397 
1398  return post_vars;
1399 }
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Definition: main/utils.c:616
static const char type[]
Definition: chan_ooh323.c:109
static char * ast_http_get_contents(int *return_length, struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
Returns the contents (body) of the HTTP request.
Definition: http.c:1181
Definition: ast_expr2.c:325
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static char * get_content_type(struct ast_variable *headers)
Retrieves the content type specified in the "Content-Type" header.
Definition: http.c:761
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ast_variable_new(name, value, filename)
const struct ast_flags ast_uri_http_legacy
Definition: main/utils.c:574
int errno
#define ast_free(a)
Definition: astmm.h:182
char * strsep(char **str, const char *delims)

◆ ast_http_header_match()

int ast_http_header_match ( const char *  name,
const char *  expected_name,
const char *  value,
const char *  expected_value 
)

Check if the header and value match (case insensitive) their associated expected values.

Parameters
nameheader name to check
expected_namethe expected name of the header
valueheader value to check
expected_valuethe expected value of the header
Returns
0 if the name and expected name do not match
-1 if the value and expected value do not match
1 if the both the name and value match their expected value
Since
13

Definition at line 1710 of file http.c.

References ast_log, and LOG_ERROR.

Referenced by websocket_client_handshake_get_response().

1712 {
1713  if (strcasecmp(name, expected_name)) {
1714  /* no value to validate if names don't match */
1715  return 0;
1716  }
1717 
1718  if (strcasecmp(value, expected_value)) {
1719  ast_log(LOG_ERROR, "Invalid header value - expected %s "
1720  "received %s", value, expected_value);
1721  return -1;
1722  }
1723  return 1;
1724 }
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static const char name[]
Definition: cdr_mysql.c:74

◆ ast_http_header_match_in()

int ast_http_header_match_in ( const char *  name,
const char *  expected_name,
const char *  value,
const char *  expected_value 
)

Check if the header name matches the expected header name. If so, then check to see if the value can be located in the expected value.

Note
Both header and value checks are case insensitive.
Parameters
nameheader name to check
expected_namethe expected name of the header
valueheader value to check if in expected value
expected_valuethe expected value(s)
Returns
0 if the name and expected name do not match
-1 if the value and is not in the expected value
1 if the name matches expected name and value is in expected value
Since
13

Definition at line 1726 of file http.c.

References ast_log, LOG_ERROR, and strcasestr().

Referenced by websocket_client_handshake_get_response().

1728 {
1729  if (strcasecmp(name, expected_name)) {
1730  /* no value to validate if names don't match */
1731  return 0;
1732  }
1733 
1734  if (!strcasestr(expected_value, value)) {
1735  ast_log(LOG_ERROR, "Header '%s' - could not locate '%s' "
1736  "in '%s'\n", name, value, expected_value);
1737  return -1;
1738 
1739  }
1740  return 1;
1741 }
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
char * strcasestr(const char *, const char *)
static const char name[]
Definition: cdr_mysql.c:74

◆ ast_http_header_parse()

int ast_http_header_parse ( char *  buf,
char **  name,
char **  value 
)

Parse a header into the given name/value strings.

Note
This modifies the given buffer and the out parameters point (not allocated) to the start of the header name and header value, respectively.
Parameters
bufa string containing the name/value to point to
nameout parameter pointing to the header name
valueout parameter pointing to header value
Returns
-1 if buf is empty
0 if buf could be separated into name and value
1 if name or value portion don't exist
Since
13

Definition at line 1688 of file http.c.

References ast_skip_blanks(), ast_strlen_zero, ast_trim_blanks(), buf, remove_excess_lws(), and strsep().

Referenced by websocket_client_handshake_get_response().

1689 {
1691  if (ast_strlen_zero(buf)) {
1692  return -1;
1693  }
1694 
1695  *value = buf;
1696  *name = strsep(value, ":");
1697  if (!*value) {
1698  return 1;
1699  }
1700 
1703  return 1;
1704  }
1705 
1707  return 0;
1708 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:182
static const char name[]
Definition: cdr_mysql.c:74
char * strsep(char **str, const char *delims)
static void remove_excess_lws(char *s)
Definition: http.c:1659

◆ ast_http_manid_from_vars()

uint32_t ast_http_manid_from_vars ( struct ast_variable headers)

Return manager id, if exist, from request headers.

Parameters
headersList of HTTP headers
Returns
32-bit associated manager session identifier
Since
1.8

Definition at line 217 of file http.c.

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

Referenced by generic_http_callback(), http_post_callback(), and static_callback().

218 {
219  uint32_t mngid = 0;
220  struct ast_variable *v, *cookies;
221 
222  cookies = ast_http_get_cookies(headers);
223  for (v = cookies; v; v = v->next) {
224  if (!strcasecmp(v->name, "mansession_id")) {
225  sscanf(v->value, "%30x", &mngid);
226  break;
227  }
228  }
229  ast_variables_destroy(cookies);
230  return mngid;
231 }
struct ast_variable * next
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
struct ast_variable * ast_http_get_cookies(struct ast_variable *headers)
Get cookie from Request headers.
Definition: http.c:1532
Structure for variables, used for configurations and for channel variables.

◆ ast_http_prefix()

void ast_http_prefix ( char *  buf,
int  len 
)

Return the current prefix.

Parameters
[out]bufdestination buffer for previous
[in]lenlength of prefix to copy
Since
1.6.1

Definition at line 233 of file http.c.

References ast_copy_string(), and prefix.

234 {
235  if (buf) {
237  }
238 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char prefix[MAX_PREFIX]
Definition: http.c:141

◆ ast_http_request_close_on_completion()

void ast_http_request_close_on_completion ( struct ast_tcptls_session_instance ser)

Request the HTTP connection be closed after this HTTP request.

Since
12.4.0
Parameters
serHTTP TCP/TLS session object.
Note
Call before ast_http_error() to make the connection close.
Returns
Nothing

Definition at line 836 of file http.c.

References ast_set_flag, http_worker_private_data::flags, HTTP_FLAG_CLOSE_ON_COMPLETION, ast_tcptls_session_instance::private_data, and request().

Referenced by ast_ari_callback(), auth_http_callback(), generic_http_callback(), handle_uri(), http_callback(), http_post_callback(), httpstatus_callback(), static_callback(), and websocket_bad_request().

837 {
839 
841 }
#define ast_set_flag(p, flag)
Definition: utils.h:70
struct ast_flags flags
Definition: http.c:453
static int request(void *obj)
Definition: chan_pjsip.c:2559

◆ ast_http_response_status_line()

int ast_http_response_status_line ( const char *  buf,
const char *  version,
int  code 
)

Parse the http response status line.

Parameters
bufthe http response line information
versionthe expected http version (e.g. HTTP/1.1)
codethe expected status code
Returns
-1 if version didn't match or status code conversion fails.
status code (>0)
Since
13

Definition at line 1636 of file http.c.

References ast_log, and LOG_ERROR.

Referenced by websocket_client_handshake_get_response().

1637 {
1638  int status_code;
1639  size_t size = strlen(version);
1640 
1641  if (strncmp(buf, version, size) || buf[size] != ' ') {
1642  ast_log(LOG_ERROR, "HTTP version not supported - "
1643  "expected %s\n", version);
1644  return -1;
1645  }
1646 
1647  /* skip to status code (version + space) */
1648  buf += size + 1;
1649 
1650  if (sscanf(buf, "%d", &status_code) != 1) {
1651  ast_log(LOG_ERROR, "Could not read HTTP status code - "
1652  "%s\n", buf);
1653  return -1;
1654  }
1655 
1656  return status_code;
1657 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391

◆ ast_http_send()

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,
int  fd,
unsigned int  static_content 
)

Generic function for sending HTTP/1.1 response.

Parameters
serTCP/TLS session object
methodGET/POST/HEAD
status_codeHTTP response code (200/401/403/404/500)
status_titleEnglish equivalent to the status_code parameter
http_headerAn ast_str object containing all headers
outAn ast_str object containing the body of the response
fdIf out is NULL, a file descriptor where the body of the response is held (otherwise -1)
static_contentZero 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 456 of file http.c.

References ast_assert, ast_debug, ast_free, ast_http_body_discard(), AST_HTTP_HEAD, ast_iostream_printf(), ast_iostream_write(), ast_localtime(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_str_strlen(), ast_strftime(), ast_strlen_zero, ast_tcptls_close_session_file(), ast_test_flag, ast_tvnow(), buf, errno, http_worker_private_data::flags, HTTP_FLAG_CLOSE_ON_COMPLETION, http_server_name, len(), MAX_SERVER_NAME_LENGTH, ast_tcptls_session_instance::private_data, request(), session_keep_alive, and ast_tcptls_session_instance::stream.

Referenced by ast_ari_callback(), ast_http_create_response(), auth_http_callback(), generic_http_callback(), handle_uri(), http_callback(), httpstatus_callback(), static_callback(), and websocket_bad_request().

460 {
461  struct timeval now = ast_tvnow();
462  struct ast_tm tm;
463  char timebuf[80];
464  char buf[256];
465  int len;
466  int content_length = 0;
467  int close_connection;
468  struct ast_str *server_header_field = ast_str_create(MAX_SERVER_NAME_LENGTH);
469  int send_content;
470 
471  if (!ser || !server_header_field) {
472  /* The connection is not open. */
473  ast_free(http_header);
474  ast_free(out);
475  ast_free(server_header_field);
476  return;
477  }
478 
480  ast_str_set(&server_header_field,
481  0,
482  "Server: %s\r\n",
484  }
485 
486  /*
487  * We shouldn't be sending non-final status codes to this
488  * function because we may close the connection before
489  * returning.
490  */
491  ast_assert(200 <= status_code);
492 
493  if (session_keep_alive <= 0) {
494  close_connection = 1;
495  } else {
497 
498  request = ser->private_data;
499  if (!request
501  || ast_http_body_discard(ser)) {
502  close_connection = 1;
503  } else {
504  close_connection = 0;
505  }
506  }
507 
508  ast_strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", ast_localtime(&now, &tm, "GMT"));
509 
510  /* calc content length */
511  if (out) {
512  content_length += ast_str_strlen(out);
513  }
514 
515  if (fd) {
516  content_length += lseek(fd, 0, SEEK_END);
517  lseek(fd, 0, SEEK_SET);
518  }
519 
520  send_content = method != AST_HTTP_HEAD || status_code >= 400;
521 
522  /* send http header */
523  if (ast_iostream_printf(ser->stream,
524  "HTTP/1.1 %d %s\r\n"
525  "%s"
526  "Date: %s\r\n"
527  "%s"
528  "%s"
529  "%s"
530  "Content-Length: %d\r\n"
531  "\r\n"
532  "%s",
533  status_code, status_title ? status_title : "OK",
534  ast_str_buffer(server_header_field),
535  timebuf,
536  close_connection ? "Connection: close\r\n" : "",
537  static_content ? "" : "Cache-Control: no-cache, no-store\r\n",
538  http_header ? ast_str_buffer(http_header) : "",
539  content_length,
540  send_content && out && ast_str_strlen(out) ? ast_str_buffer(out) : ""
541  ) <= 0) {
542  ast_debug(1, "ast_iostream_printf() failed: %s\n", strerror(errno));
543  close_connection = 1;
544  } else if (send_content && fd) {
545  /* send file content */
546  while ((len = read(fd, buf, sizeof(buf))) > 0) {
547  if (ast_iostream_write(ser->stream, buf, len) != len) {
548  ast_debug(1, "ast_iostream_write() failed: %s\n", strerror(errno));
549  close_connection = 1;
550  break;
551  }
552  }
553  }
554 
555  ast_free(http_header);
556  ast_free(out);
557  ast_free(server_header_field);
558 
559  if (close_connection) {
560  ast_debug(1, "HTTP closing session. status_code:%d\n", status_code);
562  } else {
563  ast_debug(1, "HTTP keeping session open. status_code:%d\n", status_code);
564  }
565 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
ssize_t ast_iostream_write(struct ast_iostream *stream, const void *buffer, size_t count)
Write data to an iostream.
Definition: iostream.c:374
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_assert(a)
Definition: utils.h:695
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define MAX_SERVER_NAME_LENGTH
Definition: http.c:79
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int ast_http_body_discard(struct ast_tcptls_session_instance *ser)
Read and discard any unread HTTP request body.
Definition: http.c:1120
const char * method
Definition: res_pjsip.c:4335
ssize_t ast_iostream_printf(struct ast_iostream *stream, const char *format,...)
Write a formatted string to an iostream.
Definition: iostream.c:491
static char http_server_name[MAX_SERVER_NAME_LENGTH]
Definition: http.c:104
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct ast_flags flags
Definition: http.c:453
int errno
#define ast_free(a)
Definition: astmm.h:182
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
static int request(void *obj)
Definition: chan_pjsip.c:2559
struct ast_iostream * stream
Definition: tcptls.h:160
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
void ast_tcptls_close_session_file(struct ast_tcptls_session_instance *tcptls_session)
Closes a tcptls session instance&#39;s file and/or file descriptor. The tcptls_session will be set to NUL...
Definition: tcptls.c:839
static int session_keep_alive
Definition: http.c:108
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ ast_http_uri_link()

int ast_http_uri_link ( struct ast_http_uri urih)

Link the new uri into the list.

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 673 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(), ast_http_uri::prefix, prefix, and ast_http_uri::uri.

Referenced by __ast_http_load(), __ast_http_post_load(), __init_manager(), load_module(), and reload_module().

674 {
675  struct ast_http_uri *uri;
676  int len = strlen(urih->uri);
677 
679 
680  urih->prefix = prefix;
681 
682  if ( AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len ) {
685  return 0;
686  }
687 
688  AST_RWLIST_TRAVERSE(&uris, uri, entry) {
689  if (AST_RWLIST_NEXT(uri, entry) &&
690  strlen(AST_RWLIST_NEXT(uri, entry)->uri) <= len) {
691  AST_RWLIST_INSERT_AFTER(&uris, uri, urih, entry);
693 
694  return 0;
695  }
696  }
697 
699 
701 
702  return 0;
703 }
#define AST_RWLIST_NEXT
Definition: linkedlists.h:440
#define AST_RWLIST_INSERT_AFTER
Definition: linkedlists.h:701
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:717
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const char * prefix
Definition: http.h:104
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
Definition of a URI handler.
Definition: http.h:100
Definition: search.h:40
Definition: http.c:138
const char * uri
Definition: http.h:103
#define AST_RWLIST_FIRST
Definition: linkedlists.h:422
static char prefix[MAX_PREFIX]
Definition: http.c:141

◆ ast_http_uri_unlink()

void ast_http_uri_unlink ( struct ast_http_uri urih)

Unregister a URI handler.

Definition at line 705 of file http.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by __ast_http_load(), __init_manager(), load_module(), reload_module(), and unload_module().

706 {
708  AST_RWLIST_REMOVE(&uris, urih, entry);
710 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:884
Definition: search.h:40
Definition: http.c:138

◆ ast_http_uri_unlink_all_with_key()

void ast_http_uri_unlink_all_with_key ( const char *  key)

Unregister all handlers with matching key.

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

Referenced by __ast_http_post_load(), and unload_module().

713 {
714  struct ast_http_uri *urih;
717  if (!strcmp(urih->key, key)) {
719  if (urih->dmallocd) {
720  ast_free(urih->data);
721  }
722  if (urih->mallocd) {
723  ast_free(urih);
724  }
725  }
726  }
729 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const char * key
Definition: http.h:116
unsigned int mallocd
Definition: http.h:108
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define ast_free(a)
Definition: astmm.h:182
Definition of a URI handler.
Definition: http.h:100
unsigned int dmallocd
Definition: http.h:110
Definition: search.h:40
Definition: http.c:138
void * data
Definition: http.h:114
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 2388 of file http.c.

◆ auth_create()

static struct ast_http_auth* auth_create ( const char *  userid,
const char *  password 
)
static

Definition at line 1545 of file http.c.

References ao2_alloc, ast_log, LOG_ERROR, NULL, ast_http_auth::password, and ast_http_auth::userid.

Referenced by ast_http_get_auth().

1546 {
1547  struct ast_http_auth *auth;
1548  size_t userid_len;
1549  size_t password_len;
1550 
1551  if (!userid || !password) {
1552  ast_log(LOG_ERROR, "Invalid userid/password\n");
1553  return NULL;
1554  }
1555 
1556  userid_len = strlen(userid) + 1;
1557  password_len = strlen(password) + 1;
1558 
1559  /* Allocate enough room to store everything in one memory block */
1560  auth = ao2_alloc(sizeof(*auth) + userid_len + password_len, NULL);
1561  if (!auth) {
1562  return NULL;
1563  }
1564 
1565  /* Put the userid right after the struct */
1566  auth->userid = (char *)(auth + 1);
1567  strcpy(auth->userid, userid);
1568 
1569  /* Put the password right after the userid */
1570  auth->password = auth->userid + userid_len;
1571  strcpy(auth->password, password);
1572 
1573  return auth;
1574 }
char * userid
Definition: http.h:125
#define NULL
Definition: resample.c:96
static struct ast_str * password
Definition: cdr_mysql.c:77
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
char * password
Definition: http.h:127
HTTP authentication information.
Definition: http.h:123

◆ chunked_atoh()

static int chunked_atoh ( const char *  s,
int  len 
)
static

Definition at line 987 of file http.c.

References c, and value.

Referenced by http_body_get_chunk_length().

988 {
989  int value = 0;
990  char c;
991 
992  if (*s < '0') {
993  /* zero value must be 0\n not just \n */
994  return -1;
995  }
996 
997  while (len--) {
998  c = *s++;
999  if (c == '\x0D') {
1000  return value;
1001  }
1002  if (c == ';') {
1003  /* We have a chunk-extension that we don't care about. */
1004  while (len--) {
1005  if (*s++ == '\x0D') {
1006  return value;
1007  }
1008  }
1009  break;
1010  }
1011  value <<= 4;
1012  if (c >= '0' && c <= '9') {
1013  value += c - '0';
1014  continue;
1015  }
1016  if (c >= 'a' && c <= 'f') {
1017  value += 10 + c - 'a';
1018  continue;
1019  }
1020  if (c >= 'A' && c <= 'F') {
1021  value += 10 + c - 'A';
1022  continue;
1023  }
1024  /* invalid character */
1025  return -1;
1026  }
1027  /* end of string */
1028  return -1;
1029 }
static struct test_val c
int value
Definition: syslog.c:37
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ get_content_length()

static int get_content_length ( struct ast_variable headers)
static

Returns the value of the Content-Length header.

Parameters
headersHTTP headers.
Return values
lengthValue of the Content-Length header.
0if header is not present.
-1if header is invalid.

Definition at line 786 of file http.c.

References get_header().

Referenced by http_request_tracking_setup().

787 {
788  const char *content_length = get_header(headers, "Content-Length");
789  int length;
790 
791  if (!content_length) {
792  /* Missing content length; assume zero */
793  return 0;
794  }
795 
796  length = 0;
797  if (sscanf(content_length, "%30d", &length) != 1) {
798  /* Invalid Content-Length value */
799  length = -1;
800  }
801  return length;
802 }
static const char * get_header(struct ast_variable *headers, const char *field_name)
Retrieves the header with the given field name.
Definition: http.c:739

◆ get_content_type()

static char* get_content_type ( struct ast_variable headers)
static

Retrieves the content type specified in the "Content-Type" header.

This function only returns the "type/subtype" and any trailing parameter is not included.

Note
the return value is an allocated string that needs to be freed.
Return values
thecontent type/subtype or NULL if the header is not found.

Definition at line 761 of file http.c.

References ast_strndup, get_header(), and NULL.

Referenced by ast_http_get_json(), and ast_http_get_post_vars().

762 {
763  const char *content_type = get_header(headers, "Content-Type");
764  const char *param;
765  size_t size;
766 
767  if (!content_type) {
768  return NULL;
769  }
770 
771  param = strchr(content_type, ';');
772  size = param ? param - content_type : strlen(content_type);
773 
774  return ast_strndup(content_type, size);
775 }
#define NULL
Definition: resample.c:96
static const char * get_header(struct ast_variable *headers, const char *field_name)
Retrieves the header with the given field name.
Definition: http.c:739
#define ast_strndup(str, len)
A wrapper for strndup()
Definition: astmm.h:258

◆ get_header()

static const char* get_header ( struct ast_variable headers,
const char *  field_name 
)
static

Retrieves the header with the given field name.

Parameters
headersHeaders to search.
field_nameName of the header to find.
Returns
Associated header value.
NULL if header is not present.

Definition at line 739 of file http.c.

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

Referenced by get_content_length(), get_content_type(), get_transfer_encoding(), and http_check_connection_close().

740 {
741  struct ast_variable *v;
742 
743  for (v = headers; v; v = v->next) {
744  if (!strcasecmp(v->name, field_name)) {
745  return v->value;
746  }
747  }
748  return NULL;
749 }
struct ast_variable * next
Structure for variables, used for configurations and for channel variables.
#define NULL
Definition: resample.c:96

◆ get_transfer_encoding()

static const char* get_transfer_encoding ( struct ast_variable headers)
static

Returns the value of the Transfer-Encoding header.

Parameters
headersHTTP headers.
Return values
stringValue of the Transfer-Encoding header.
NULLif header is not present.

Definition at line 811 of file http.c.

References get_header().

Referenced by http_request_tracking_setup(), and httpd_process_request().

812 {
813  return get_header(headers, "Transfer-Encoding");
814 }
static const char * get_header(struct ast_variable *headers, const char *field_name)
Retrieves the header with the given field name.
Definition: http.c:739

◆ handle_show_http()

static char* handle_show_http ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2279 of file http.c.

References ast_cli_args::argc, ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_sockaddr_isnull(), ast_sockaddr_stringify(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_http_uri::description, http_uri_redirect::dest, ast_tls_config::enabled, ast_cli_args::fd, ast_http_uri::has_subtree, http_server_name, http_tls_cfg, NULL, ast_tcptls_session_args::old_address, prefix, http_uri_redirect::target, ast_http_uri::uri, and ast_cli_entry::usage.

2280 {
2281  struct ast_http_uri *urih;
2282  struct http_uri_redirect *redirect;
2283 
2284  switch (cmd) {
2285  case CLI_INIT:
2286  e->command = "http show status";
2287  e->usage =
2288  "Usage: http show status\n"
2289  " Lists status of internal HTTP engine\n";
2290  return NULL;
2291  case CLI_GENERATE:
2292  return NULL;
2293  }
2294 
2295  if (a->argc != 3) {
2296  return CLI_SHOWUSAGE;
2297  }
2298  ast_cli(a->fd, "HTTP Server Status:\n");
2299  ast_cli(a->fd, "Prefix: %s\n", prefix);
2300  ast_cli(a->fd, "Server: %s\n", http_server_name);
2302  ast_cli(a->fd, "Server Disabled\n\n");
2303  } else {
2304  ast_cli(a->fd, "Server Enabled and Bound to %s\n\n",
2306  if (http_tls_cfg.enabled) {
2307  ast_cli(a->fd, "HTTPS Server Enabled and Bound to %s\n\n",
2309  }
2310  }
2311 
2312  ast_cli(a->fd, "Enabled URI's:\n");
2314  if (AST_RWLIST_EMPTY(&uris)) {
2315  ast_cli(a->fd, "None.\n");
2316  } else {
2317  AST_RWLIST_TRAVERSE(&uris, urih, entry)
2318  ast_cli(a->fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
2319  }
2321 
2322  ast_cli(a->fd, "\nEnabled Redirects:\n");
2325  ast_cli(a->fd, " %s => %s\n", redirect->target, redirect->dest);
2327  ast_cli(a->fd, " None.\n");
2328  }
2330 
2331  return CLI_SUCCESS;
2332 }
const int argc
Definition: cli.h:160
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
char * dest
Definition: http.c:171
unsigned int has_subtree
Definition: http.h:106
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
static struct ast_tls_config http_tls_cfg
Definition: http.c:111
static struct ast_tcptls_session_args http_desc
Definition: http.c:118
static char http_server_name[MAX_SERVER_NAME_LENGTH]
Definition: http.c:104
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
#define CLI_SHOWUSAGE
Definition: cli.h:45
const char * description
Definition: http.h:102
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
char target[0]
Definition: http.c:172
char * command
Definition: cli.h:186
struct ast_sockaddr old_address
Definition: tcptls.h:131
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
Definition of a URI handler.
Definition: http.h:100
Definition: search.h:40
Definition: http.c:138
const char * uri
Definition: http.h:103
static struct ast_tcptls_session_args https_desc
Definition: http.c:128
static char prefix[MAX_PREFIX]
Definition: http.c:141
int enabled
Definition: tcptls.h:88

◆ handle_uri()

static int handle_uri ( struct ast_tcptls_session_instance ser,
char *  uri,
enum ast_http_method  method,
struct ast_variable headers 
)
static

Definition at line 1401 of file http.c.

References ast_debug, ast_http_error(), ast_http_request_close_on_completion(), ast_http_send(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_create, ast_str_set(), ast_uri_decode(), ast_uri_http_legacy, ast_variable_new, ast_variables_destroy(), c, ast_http_uri::callback, cleanup(), http_uri_redirect::dest, ast_http_uri::has_subtree, ast_http_uri::no_decode_uri, NULL, prefix, strsep(), http_uri_redirect::target, ast_http_uri::uri, and var.

Referenced by httpd_process_request().

1403 {
1404  char *c;
1405  int res = 0;
1406  char *params = uri;
1407  struct ast_http_uri *urih = NULL;
1408  int l;
1409  struct ast_variable *get_vars = NULL, *v, *prev = NULL;
1410  struct http_uri_redirect *redirect;
1411 
1412  ast_debug(2, "HTTP Request URI is %s \n", uri);
1413 
1414  strsep(&params, "?");
1415  /* Extract arguments from the request and store them in variables. */
1416  if (params) {
1417  char *var, *val;
1418 
1419  while ((val = strsep(&params, "&"))) {
1420  var = strsep(&val, "=");
1421  if (val) {
1423  } else {
1424  val = "";
1425  }
1427  if ((v = ast_variable_new(var, val, ""))) {
1428  if (get_vars) {
1429  prev->next = v;
1430  } else {
1431  get_vars = v;
1432  }
1433  prev = v;
1434  }
1435  }
1436  }
1437 
1439  AST_RWLIST_TRAVERSE(&uri_redirects, redirect, entry) {
1440  if (!strcasecmp(uri, redirect->target)) {
1441  struct ast_str *http_header = ast_str_create(128);
1442 
1443  if (!http_header) {
1445  ast_http_error(ser, 500, "Server Error", "Out of memory");
1446  break;
1447  }
1448  ast_str_set(&http_header, 0, "Location: %s\r\n", redirect->dest);
1449  ast_http_send(ser, method, 302, "Moved Temporarily", http_header, NULL, 0, 0);
1450  break;
1451  }
1452  }
1454  if (redirect) {
1455  goto cleanup;
1456  }
1457 
1458  /* We want requests to start with the (optional) prefix and '/' */
1459  l = strlen(prefix);
1460  if (!strncasecmp(uri, prefix, l) && uri[l] == '/') {
1461  uri += l + 1;
1462  /* scan registered uris to see if we match one. */
1464  AST_RWLIST_TRAVERSE(&uris, urih, entry) {
1465  l = strlen(urih->uri);
1466  c = uri + l; /* candidate */
1467  ast_debug(2, "match request [%s] with handler [%s] len %d\n", uri, urih->uri, l);
1468  if (strncasecmp(urih->uri, uri, l) /* no match */
1469  || (*c && *c != '/')) { /* substring */
1470  continue;
1471  }
1472  if (*c == '/') {
1473  c++;
1474  }
1475  if (!*c || urih->has_subtree) {
1476  uri = c;
1477  break;
1478  }
1479  }
1481  }
1482  if (urih) {
1483  ast_debug(1, "Match made with [%s]\n", urih->uri);
1484  if (!urih->no_decode_uri) {
1486  }
1487  res = urih->callback(ser, urih, uri, method, get_vars, headers);
1488  } else {
1489  ast_debug(1, "Requested URI [%s] has no handler\n", uri);
1490  ast_http_error(ser, 404, "Not Found", "The requested URL was not found on this server.");
1491  }
1492 
1493 cleanup:
1494  ast_variables_destroy(get_vars);
1495  return res;
1496 }
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Definition: main/utils.c:616
ast_http_callback callback
Definition: http.h:105
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
Definition: ast_expr2.c:325
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
char * dest
Definition: http.c:171
static struct test_val c
unsigned int has_subtree
Definition: http.h:106
#define NULL
Definition: resample.c:96
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
const char * method
Definition: res_pjsip.c:4335
#define ast_variable_new(name, value, filename)
const struct ast_flags ast_uri_http_legacy
Definition: main/utils.c:574
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser)
Request the HTTP connection be closed after this HTTP request.
Definition: http.c:836
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, int fd, unsigned int static_content)
Generic function for sending HTTP/1.1 response.
Definition: http.c:456
char target[0]
Definition: http.c:172
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
char * strsep(char **str, const char *delims)
Definition of a URI handler.
Definition: http.h:100
Definition: search.h:40
void ast_http_error(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
Send HTTP error message and close socket.
Definition: http.c:648
Definition: http.c:138
const char * uri
Definition: http.h:103
unsigned int no_decode_uri
Definition: http.h:112
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
static char prefix[MAX_PREFIX]
Definition: http.c:141

◆ http_body_check_chunk_sync()

static int http_body_check_chunk_sync ( struct ast_tcptls_session_instance ser)
static

Definition at line 1069 of file http.c.

References ast_iostream_read(), ast_log, LOG_WARNING, and ast_tcptls_session_instance::stream.

Referenced by ast_http_body_discard(), and ast_http_get_contents().

1070 {
1071  int res;
1072  char chunk_sync[2];
1073 
1074  /* Stay in fread until get the expected CRLF or timeout. */
1075  res = ast_iostream_read(ser->stream, chunk_sync, sizeof(chunk_sync));
1076  if (res < sizeof(chunk_sync)) {
1077  ast_log(LOG_WARNING, "Short HTTP chunk sync read (Wanted %zu)\n",
1078  sizeof(chunk_sync));
1079  return -1;
1080  }
1081  if (chunk_sync[0] != 0x0D || chunk_sync[1] != 0x0A) {
1082  ast_log(LOG_WARNING, "HTTP chunk sync bytes wrong (0x%02hhX, 0x%02hhX)\n",
1083  (unsigned char) chunk_sync[0], (unsigned char) chunk_sync[1]);
1084  return -1;
1085  }
1086 
1087  return 0;
1088 }
#define LOG_WARNING
Definition: logger.h:274
ssize_t ast_iostream_read(struct ast_iostream *stream, void *buffer, size_t count)
Read data from an iostream.
Definition: iostream.c:273
#define ast_log
Definition: astobj2.c:42
struct ast_iostream * stream
Definition: tcptls.h:160

◆ http_body_discard_chunk_trailer_headers()

static int http_body_discard_chunk_trailer_headers ( struct ast_tcptls_session_instance ser)
static

Definition at line 1100 of file http.c.

References ast_iostream_gets(), ast_log, ast_strlen_zero, ast_trim_blanks(), LOG_WARNING, MAX_HTTP_LINE_LENGTH, and ast_tcptls_session_instance::stream.

Referenced by ast_http_body_discard(), and ast_http_get_contents().

1101 {
1102  char header_line[MAX_HTTP_LINE_LENGTH];
1103 
1104  for (;;) {
1105  if (ast_iostream_gets(ser->stream, header_line, sizeof(header_line)) <= 0) {
1106  ast_log(LOG_WARNING, "Short HTTP read of chunked trailer header\n");
1107  return -1;
1108  }
1109 
1110  /* Trim trailing whitespace */
1111  ast_trim_blanks(header_line);
1112  if (ast_strlen_zero(header_line)) {
1113  /* A blank line ends the chunked-body */
1114  break;
1115  }
1116  }
1117  return 0;
1118 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:182
struct ast_iostream * stream
Definition: tcptls.h:160
ssize_t ast_iostream_gets(struct ast_iostream *stream, char *buffer, size_t size)
Read a LF-terminated string from an iostream.
Definition: iostream.c:300
#define MAX_HTTP_LINE_LENGTH
Definition: http.c:99

◆ http_body_discard_contents()

static int http_body_discard_contents ( struct ast_tcptls_session_instance ser,
int  length,
const char *  what_getting 
)
static

Definition at line 964 of file http.c.

References ast_iostream_discard(), ast_log, LOG_WARNING, and ast_tcptls_session_instance::stream.

Referenced by ast_http_body_discard().

965 {
966  ssize_t res;
967 
968  res = ast_iostream_discard(ser->stream, length);
969  if (res < length) {
970  ast_log(LOG_WARNING, "Short HTTP request %s (Wanted %d but got %zd)\n",
971  what_getting, length, res);
972  return -1;
973  }
974  return 0;
975 }
#define LOG_WARNING
Definition: logger.h:274
ssize_t ast_iostream_discard(struct ast_iostream *stream, size_t count)
Discard the specified number of bytes from an iostream.
Definition: iostream.c:357
#define ast_log
Definition: astobj2.c:42
struct ast_iostream * stream
Definition: tcptls.h:160

◆ http_body_get_chunk_length()

static int http_body_get_chunk_length ( struct ast_tcptls_session_instance ser)
static

Definition at line 1041 of file http.c.

References ast_iostream_gets(), ast_log, chunked_atoh(), LOG_WARNING, MAX_HTTP_LINE_LENGTH, and ast_tcptls_session_instance::stream.

Referenced by ast_http_body_discard(), and ast_http_get_contents().

1042 {
1043  int length;
1044  char header_line[MAX_HTTP_LINE_LENGTH];
1045 
1046  /* get the line of hexadecimal giving chunk-size w/ optional chunk-extension */
1047  if (ast_iostream_gets(ser->stream, header_line, sizeof(header_line)) <= 0) {
1048  ast_log(LOG_WARNING, "Short HTTP read of chunked header\n");
1049  return -1;
1050  }
1051  length = chunked_atoh(header_line, strlen(header_line));
1052  if (length < 0) {
1053  ast_log(LOG_WARNING, "Invalid HTTP chunk size\n");
1054  return -1;
1055  }
1056  return length;
1057 }
#define LOG_WARNING
Definition: logger.h:274
static int chunked_atoh(const char *s, int len)
Definition: http.c:987
#define ast_log
Definition: astobj2.c:42
struct ast_iostream * stream
Definition: tcptls.h:160
ssize_t ast_iostream_gets(struct ast_iostream *stream, char *buffer, size_t size)
Read a LF-terminated string from an iostream.
Definition: iostream.c:300
#define MAX_HTTP_LINE_LENGTH
Definition: http.c:99

◆ http_body_read_contents()

static int http_body_read_contents ( struct ast_tcptls_session_instance ser,
char *  buf,
int  length,
const char *  what_getting 
)
static

Definition at line 928 of file http.c.

References ast_iostream_read(), ast_log, LOG_WARNING, ast_tcptls_session_instance::stream, and total.

Referenced by ast_http_get_contents().

929 {
930  int res;
931  int total = 0;
932 
933  /* Stream is in exclusive mode so we get it all if possible. */
934  while (total != length) {
935  res = ast_iostream_read(ser->stream, buf + total, length - total);
936  if (res <= 0) {
937  break;
938  }
939 
940  total += res;
941  }
942 
943  if (total != length) {
944  ast_log(LOG_WARNING, "Wrong HTTP content read. Request %s (Wanted %d, Read %d)\n",
945  what_getting, length, res);
946  return -1;
947  }
948 
949  return 0;
950 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
ssize_t ast_iostream_read(struct ast_iostream *stream, void *buffer, size_t count)
Read data from an iostream.
Definition: iostream.c:273
#define ast_log
Definition: astobj2.c:42
struct ast_iostream * stream
Definition: tcptls.h:160
static int total
Definition: res_adsi.c:968

◆ http_check_connection_close()

static int http_check_connection_close ( struct ast_variable headers)
static

Definition at line 825 of file http.c.

References get_header().

Referenced by http_request_tracking_setup().

826 {
827  const char *connection = get_header(headers, "Connection");
828  int close_connection = 0;
829 
830  if (connection && !strcasecmp(connection, "close")) {
831  close_connection = -1;
832  }
833  return close_connection;
834 }
static const char * get_header(struct ast_variable *headers, const char *field_name)
Retrieves the header with the given field name.
Definition: http.c:739

◆ http_request_headers_get()

static int http_request_headers_get ( struct ast_tcptls_session_instance ser,
struct ast_variable **  headers 
)
static

Definition at line 1757 of file http.c.

References ast_http_error(), ast_iostream_gets(), ast_skip_blanks(), ast_strlen_zero, ast_trim_blanks(), ast_variable_new, ast_variables_destroy(), len(), MAX_HTTP_LINE_LENGTH, MAX_HTTP_REQUEST_HEADERS, ast_tcptls_session_args::name, ast_variable::next, NULL, ast_tcptls_session_instance::stream, strsep(), and value.

Referenced by httpd_process_request().

1758 {
1759  struct ast_variable *tail = *headers;
1760  int remaining_headers;
1761  char header_line[MAX_HTTP_LINE_LENGTH];
1762 
1763  remaining_headers = MAX_HTTP_REQUEST_HEADERS;
1764  for (;;) {
1765  ssize_t len;
1766  char *name;
1767  char *value;
1768 
1769  len = ast_iostream_gets(ser->stream, header_line, sizeof(header_line));
1770  if (len <= 0) {
1771  ast_http_error(ser, 400, "Bad Request", "Timeout");
1772  return -1;
1773  }
1774  if (header_line[len - 1] != '\n') {
1775  /* We didn't get a full line */
1776  ast_http_error(ser, 400, "Bad Request",
1777  (len == sizeof(header_line) - 1) ? "Header line too long" : "Timeout");
1778  return -1;
1779  }
1780 
1781  /* Trim trailing characters */
1782  ast_trim_blanks(header_line);
1783  if (ast_strlen_zero(header_line)) {
1784  /* A blank line ends the request header section. */
1785  break;
1786  }
1787 
1788  value = header_line;
1789  name = strsep(&value, ":");
1790  if (!value) {
1791  continue;
1792  }
1793 
1794  value = ast_skip_blanks(value);
1795  if (ast_strlen_zero(value) || ast_strlen_zero(name)) {
1796  continue;
1797  }
1798 
1799  ast_trim_blanks(name);
1800 
1801  if (!remaining_headers--) {
1802  /* Too many headers. */
1803  ast_http_error(ser, 413, "Request Entity Too Large", "Too many headers");
1804  return -1;
1805  }
1806  if (!*headers) {
1807  *headers = ast_variable_new(name, value, __FILE__);
1808  tail = *headers;
1809  } else {
1810  tail->next = ast_variable_new(name, value, __FILE__);
1811  tail = tail->next;
1812  }
1813  if (!tail) {
1814  /*
1815  * Variable allocation failure.
1816  * Try to make some room.
1817  */
1818  ast_variables_destroy(*headers);
1819  *headers = NULL;
1820 
1821  ast_http_error(ser, 500, "Server Error", "Out of memory");
1822  return -1;
1823  }
1824  }
1825 
1826  return 0;
1827 }
struct ast_variable * next
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
Structure for variables, used for configurations and for channel variables.
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_variable_new(name, value, filename)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:182
static const char name[]
Definition: cdr_mysql.c:74
struct ast_iostream * stream
Definition: tcptls.h:160
ssize_t ast_iostream_gets(struct ast_iostream *stream, char *buffer, size_t size)
Read a LF-terminated string from an iostream.
Definition: iostream.c:300
char * strsep(char **str, const char *delims)
#define MAX_HTTP_REQUEST_HEADERS
Definition: http.c:1744
void ast_http_error(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
Send HTTP error message and close socket.
Definition: http.c:648
#define MAX_HTTP_LINE_LENGTH
Definition: http.c:99

◆ http_request_tracking_init()

static void http_request_tracking_init ( struct http_worker_private_data request)
static

Definition at line 852 of file http.c.

References ast_set_flags_to, http_worker_private_data::flags, HTTP_FLAG_BODY_READ, HTTP_FLAG_CLOSE_ON_COMPLETION, and HTTP_FLAG_HAS_BODY.

Referenced by httpd_helper_thread(), and httpd_process_request().

853 {
854  ast_set_flags_to(&request->flags,
856  /* Assume close in case request fails early */
858 }
#define ast_set_flags_to(p, flag, value)
Definition: utils.h:104
struct ast_flags flags
Definition: http.c:453

◆ http_request_tracking_setup()

static int http_request_tracking_setup ( struct ast_tcptls_session_instance ser,
struct ast_variable headers 
)
static

Definition at line 871 of file http.c.

References ast_http_error(), ast_set_flag, ast_set_flags_to, http_worker_private_data::body_length, http_worker_private_data::flags, get_content_length(), get_transfer_encoding(), http_check_connection_close(), HTTP_FLAG_BODY_READ, HTTP_FLAG_CLOSE_ON_COMPLETION, HTTP_FLAG_HAS_BODY, ast_tcptls_session_instance::private_data, and request().

Referenced by httpd_process_request().

872 {
874  const char *transfer_encoding;
875 
876  ast_set_flags_to(&request->flags,
879 
880  transfer_encoding = get_transfer_encoding(headers);
881  if (transfer_encoding && !strcasecmp(transfer_encoding, "chunked")) {
882  request->body_length = -1;
884  return 0;
885  }
886 
887  request->body_length = get_content_length(headers);
888  if (0 < request->body_length) {
890  } else if (request->body_length < 0) {
891  /* Invalid Content-Length */
893  ast_http_error(ser, 400, "Bad Request", "Invalid Content-Length in request!");
894  return -1;
895  }
896  return 0;
897 }
#define ast_set_flag(p, flag)
Definition: utils.h:70
static int get_content_length(struct ast_variable *headers)
Returns the value of the Content-Length header.
Definition: http.c:786
#define ast_set_flags_to(p, flag, value)
Definition: utils.h:104
struct ast_flags flags
Definition: http.c:453
static const char * get_transfer_encoding(struct ast_variable *headers)
Returns the value of the Transfer-Encoding header.
Definition: http.c:811
static int request(void *obj)
Definition: chan_pjsip.c:2559
static int http_check_connection_close(struct ast_variable *headers)
Definition: http.c:825
void ast_http_error(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
Send HTTP error message and close socket.
Definition: http.c:648

◆ httpd_helper_thread()

static void * httpd_helper_thread ( void *  arg)
static

Definition at line 1937 of file http.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_ref, ast_atomic_fetchadd_int(), ast_debug, ast_http_error(), ast_iostream_get_fd(), ast_iostream_nonblock(), ast_iostream_set_exclusive_input(), ast_iostream_set_timeout_idle_inactivity(), ast_log, ast_tcptls_close_session_file(), done, errno, http_request_tracking_init(), httpd_process_request(), LOG_WARNING, MIN_INITIAL_REQUEST_TIMEOUT, NULL, ast_tcptls_session_instance::private_data, session_count, session_inactivity, session_keep_alive, session_limit, ast_tcptls_session_instance::stream, and timeout.

1938 {
1939  struct ast_tcptls_session_instance *ser = data;
1940  int timeout;
1941  int arg = 1;
1942 
1943  if (!ser) {
1944  ao2_cleanup(ser);
1945  return NULL;
1946  }
1947 
1949  ast_log(LOG_WARNING, "HTTP session count exceeded %d sessions.\n",
1950  session_limit);
1951  goto done;
1952  }
1953  ast_debug(1, "HTTP opening session. Top level\n");
1954 
1955  /*
1956  * Here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
1957  * This is necessary to prevent delays (caused by buffering) as we
1958  * write to the socket in bits and pieces.
1959  */
1960  if (setsockopt(ast_iostream_get_fd(ser->stream), IPPROTO_TCP, TCP_NODELAY, (char *) &arg, sizeof(arg)) < 0) {
1961  ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection: %s\n", strerror(errno));
1962  }
1964 
1965  /* Setup HTTP worker private data to keep track of request body reading. */
1966  ao2_cleanup(ser->private_data);
1969  if (!ser->private_data) {
1970  ast_http_error(ser, 500, "Server Error", "Out of memory");
1971  goto done;
1972  }
1974 
1975  /* Determine initial HTTP request wait timeout. */
1976  timeout = session_keep_alive;
1977  if (timeout <= 0) {
1978  /* Persistent connections not enabled. */
1979  timeout = session_inactivity;
1980  }
1981  if (timeout < MIN_INITIAL_REQUEST_TIMEOUT) {
1982  timeout = MIN_INITIAL_REQUEST_TIMEOUT;
1983  }
1984 
1985  /* We can let the stream wait for data to arrive. */
1987 
1988  for (;;) {
1989  /* Wait for next potential HTTP request message. */
1991  if (httpd_process_request(ser)) {
1992  /* Break the connection or the connection closed */
1993  break;
1994  }
1995  if (!ser->stream) {
1996  /* Web-socket or similar that took the connection */
1997  break;
1998  }
1999 
2000  timeout = session_keep_alive;
2001  if (timeout <= 0) {
2002  /* Persistent connections not enabled. */
2003  break;
2004  }
2005  }
2006 
2007 done:
2009 
2010  ast_debug(1, "HTTP closing session. Top level\n");
2012 
2013  ao2_ref(ser, -1);
2014  return NULL;
2015 }
void ast_iostream_set_exclusive_input(struct ast_iostream *stream, int exclusive_input)
Set the iostream if it can exclusively depend upon the set timeouts.
Definition: iostream.c:148
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
int ast_iostream_get_fd(struct ast_iostream *stream)
Get an iostream&#39;s file descriptor.
Definition: iostream.c:84
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
void ast_iostream_set_timeout_idle_inactivity(struct ast_iostream *stream, int timeout, int timeout_reset)
Set the iostream inactivity & idle timeout timers.
Definition: iostream.c:130
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
int done
Definition: test_amihooks.c:48
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
describes a server instance
Definition: tcptls.h:149
static int httpd_process_request(struct ast_tcptls_session_instance *ser)
Definition: http.c:1839
static int session_limit
Definition: http.c:106
int errno
static void http_request_tracking_init(struct http_worker_private_data *request)
Definition: http.c:852
static int session_inactivity
Definition: http.c:107
#define MIN_INITIAL_REQUEST_TIMEOUT
Definition: http.c:75
static int session_count
Definition: http.c:109
struct ast_iostream * stream
Definition: tcptls.h:160
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_tcptls_close_session_file(struct ast_tcptls_session_instance *tcptls_session)
Closes a tcptls session instance&#39;s file and/or file descriptor. The tcptls_session will be set to NUL...
Definition: tcptls.c:839
void ast_iostream_nonblock(struct ast_iostream *stream)
Make an iostream non-blocking.
Definition: iostream.c:103
void ast_http_error(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
Send HTTP error message and close socket.
Definition: http.c:648
static int session_keep_alive
Definition: http.c:108

◆ httpd_process_request()

static int httpd_process_request ( struct ast_tcptls_session_instance ser)
static

Definition at line 1839 of file http.c.

References AST_HTTP_DELETE, ast_http_error(), AST_HTTP_GET, AST_HTTP_HEAD, AST_HTTP_OPTIONS, AST_HTTP_POST, AST_HTTP_PUT, AST_HTTP_UNKNOWN, ast_iostream_gets(), ast_shutdown_final(), ast_skip_blanks(), ast_skip_nonblanks(), ast_test_flag, ast_variables_destroy(), c, http_worker_private_data::flags, get_transfer_encoding(), handle_uri(), HTTP_FLAG_CLOSE_ON_COMPLETION, http_request_headers_get(), http_request_tracking_init(), http_request_tracking_setup(), len(), MAX_HTTP_LINE_LENGTH, method, NULL, ast_tcptls_session_instance::private_data, RAII_VAR, request(), and ast_tcptls_session_instance::stream.

Referenced by httpd_helper_thread().

1840 {
1841  RAII_VAR(struct ast_variable *, headers, NULL, ast_variables_destroy);
1842  char *uri;
1843  char *method;
1844  const char *transfer_encoding;
1846  enum ast_http_method http_method = AST_HTTP_UNKNOWN;
1847  int res;
1848  ssize_t len;
1849  char request_line[MAX_HTTP_LINE_LENGTH];
1850 
1851  len = ast_iostream_gets(ser->stream, request_line, sizeof(request_line));
1852  if (len <= 0) {
1853  return -1;
1854  }
1855 
1856  /* Re-initialize the request body tracking data. */
1857  request = ser->private_data;
1858  http_request_tracking_init(request);
1859 
1860  if (request_line[len - 1] != '\n') {
1861  /* We didn't get a full line */
1862  ast_http_error(ser, 400, "Bad Request",
1863  (len == sizeof(request_line) - 1) ? "Request line too long" : "Timeout");
1864  return -1;
1865  }
1866 
1867  /* Get method */
1868  method = ast_skip_blanks(request_line);
1869  uri = ast_skip_nonblanks(method);
1870  if (*uri) {
1871  *uri++ = '\0';
1872  }
1873 
1874  if (!strcasecmp(method,"GET")) {
1875  http_method = AST_HTTP_GET;
1876  } else if (!strcasecmp(method,"POST")) {
1877  http_method = AST_HTTP_POST;
1878  } else if (!strcasecmp(method,"HEAD")) {
1879  http_method = AST_HTTP_HEAD;
1880  } else if (!strcasecmp(method,"PUT")) {
1881  http_method = AST_HTTP_PUT;
1882  } else if (!strcasecmp(method,"DELETE")) {
1883  http_method = AST_HTTP_DELETE;
1884  } else if (!strcasecmp(method,"OPTIONS")) {
1885  http_method = AST_HTTP_OPTIONS;
1886  }
1887 
1888  uri = ast_skip_blanks(uri); /* Skip white space */
1889  if (*uri) { /* terminate at the first blank */
1890  char *c = ast_skip_nonblanks(uri);
1891 
1892  if (*c) {
1893  *c = '\0';
1894  }
1895  } else {
1896  ast_http_error(ser, 400, "Bad Request", "Invalid Request");
1897  return -1;
1898  }
1899 
1900  if (ast_shutdown_final()) {
1901  ast_http_error(ser, 503, "Service Unavailable", "Shutdown in progress");
1902  return -1;
1903  }
1904 
1905  /* process "Request Headers" lines */
1906  if (http_request_headers_get(ser, &headers)) {
1907  return -1;
1908  }
1909 
1910  transfer_encoding = get_transfer_encoding(headers);
1911  /* Transfer encoding defaults to identity */
1912  if (!transfer_encoding) {
1913  transfer_encoding = "identity";
1914  }
1915 
1916  /*
1917  * RFC 2616, section 3.6, we should respond with a 501 for any transfer-
1918  * codings we don't understand.
1919  */
1920  if (strcasecmp(transfer_encoding, "identity") != 0 &&
1921  strcasecmp(transfer_encoding, "chunked") != 0) {
1922  /* Transfer encodings not supported */
1923  ast_http_error(ser, 501, "Unimplemented", "Unsupported Transfer-Encoding.");
1924  return -1;
1925  }
1926 
1927  if (http_request_tracking_setup(ser, headers)
1928  || handle_uri(ser, uri, http_method, headers)
1930  res = -1;
1931  } else {
1932  res = 0;
1933  }
1934  return res;
1935 }
static int http_request_headers_get(struct ast_tcptls_session_instance *ser, struct ast_variable **headers)
Definition: http.c:1757
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
#define ast_test_flag(p, flag)
Definition: utils.h:63
Structure for variables, used for configurations and for channel variables.
static struct test_val c
#define NULL
Definition: resample.c:96
static int http_request_tracking_setup(struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
Definition: http.c:871
char * ast_skip_nonblanks(const char *str)
Gets a pointer to first whitespace character in a string.
Definition: strings.h:200
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
const char * method
Definition: res_pjsip.c:4335
int ast_shutdown_final(void)
Definition: asterisk.c:1829
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct ast_flags flags
Definition: http.c:453
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
static void http_request_tracking_init(struct http_worker_private_data *request)
Definition: http.c:852
static const char * get_transfer_encoding(struct ast_variable *headers)
Returns the value of the Transfer-Encoding header.
Definition: http.c:811
static int request(void *obj)
Definition: chan_pjsip.c:2559
struct ast_iostream * stream
Definition: tcptls.h:160
static int handle_uri(struct ast_tcptls_session_instance *ser, char *uri, enum ast_http_method method, struct ast_variable *headers)
Definition: http.c:1401
ssize_t ast_iostream_gets(struct ast_iostream *stream, char *buffer, size_t size)
Read a LF-terminated string from an iostream.
Definition: iostream.c:300
void ast_http_error(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
Send HTTP error message and close socket.
Definition: http.c:648
ast_http_method
HTTP Request methods known by Asterisk.
Definition: http.h:56
#define MAX_HTTP_LINE_LENGTH
Definition: http.c:99

◆ httpstatus_callback()

static int httpstatus_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_vars,
struct ast_variable headers 
)
static

Definition at line 368 of file http.c.

References ast_http_error(), AST_HTTP_GET, ast_http_get_cookies(), AST_HTTP_HEAD, ast_http_request_close_on_completion(), ast_http_send(), ast_sockaddr_stringify_addr(), ast_sockaddr_stringify_port(), ast_str_append(), ast_str_create, ast_variables_destroy(), ast_tls_config::enabled, http_server_name, http_tls_cfg, ast_variable::name, ast_variable::next, NULL, ast_tcptls_session_args::old_address, out, prefix, and ast_variable::value.

372 {
373  struct ast_str *out;
374  struct ast_variable *v, *cookies = NULL;
375 
376  if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) {
377  ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
378  return 0;
379  }
380 
381  out = ast_str_create(512);
382  if (!out) {
384  ast_http_error(ser, 500, "Server Error", "Out of memory");
385  return 0;
386  }
387 
388  ast_str_append(&out, 0,
389  "<html><title>Asterisk HTTP Status</title>\r\n"
390  "<body bgcolor=\"#ffffff\">\r\n"
391  "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n"
392  "<h2>&nbsp;&nbsp;Asterisk&trade; HTTP Status</h2></td></tr>\r\n");
393 
394  ast_str_append(&out, 0, "<tr><td><i>Server</i></td><td><b>%s</b></td></tr>\r\n", http_server_name);
395  ast_str_append(&out, 0, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix);
396  ast_str_append(&out, 0, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
398  ast_str_append(&out, 0, "<tr><td><i>Bind Port</i></td><td><b>%s</b></td></tr>\r\n",
400  if (http_tls_cfg.enabled) {
401  ast_str_append(&out, 0, "<tr><td><i>SSL Bind Port</i></td><td><b>%s</b></td></tr>\r\n",
403  }
404  ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
405  for (v = get_vars; v; v = v->next) {
406  ast_str_append(&out, 0, "<tr><td><i>Submitted GET Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
407  }
408  ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
409 
410  cookies = ast_http_get_cookies(headers);
411  for (v = cookies; v; v = v->next) {
412  ast_str_append(&out, 0, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
413  }
414  ast_variables_destroy(cookies);
415 
416  ast_str_append(&out, 0, "</table><center><font size=\"-1\"><i>Asterisk and Digium are registered trademarks of Digium, Inc.</i></font></center></body></html>\r\n");
417  ast_http_send(ser, method, 200, NULL, NULL, out, 0, 0);
418  return 0;
419 }
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Definition: netsock2.h:290
struct ast_variable * next
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
struct ast_variable * ast_http_get_cookies(struct ast_variable *headers)
Get cookie from Request headers.
Definition: http.c:1532
Structure for variables, used for configurations and for channel variables.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define NULL
Definition: resample.c:96
static char * ast_sockaddr_stringify_port(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return a port only.
Definition: netsock2.h:362
static struct ast_tls_config http_tls_cfg
Definition: http.c:111
const char * method
Definition: res_pjsip.c:4335
static struct ast_tcptls_session_args http_desc
Definition: http.c:118
static char http_server_name[MAX_SERVER_NAME_LENGTH]
Definition: http.c:104
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser)
Request the HTTP connection be closed after this HTTP request.
Definition: http.c:836
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, int fd, unsigned int static_content)
Generic function for sending HTTP/1.1 response.
Definition: http.c:456
struct ast_sockaddr old_address
Definition: tcptls.h:131
FILE * out
Definition: utils/frame.c:33
void ast_http_error(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
Send HTTP error message and close socket.
Definition: http.c:648
static struct ast_tcptls_session_args https_desc
Definition: http.c:128
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
static char prefix[MAX_PREFIX]
Definition: http.c:141
int enabled
Definition: tcptls.h:88

◆ load_module()

static int load_module ( void  )
static

Definition at line 2374 of file http.c.

References __ast_http_load(), ARRAY_LEN, ast_cli_register_multiple, AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CORE, AST_MODULE_INFO(), AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, reload(), reload_module(), and unload_module().

2375 {
2377 
2379 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct ast_cli_entry cli_http[]
Definition: http.c:2339
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static int __ast_http_load(int reload)
Definition: http.c:2077
Module could not be loaded properly.
Definition: module.h:102

◆ parse_cookies()

static struct ast_variable* parse_cookies ( const char *  cookies)
static

Definition at line 1498 of file http.c.

References ast_debug, ast_strdupa, ast_strip(), ast_strip_quoted(), ast_strlen_zero, ast_variable_new, ast_tcptls_session_args::name, NULL, parse(), strsep(), and var.

Referenced by ast_http_get_cookies().

1499 {
1500  char *parse = ast_strdupa(cookies);
1501  char *cur;
1502  struct ast_variable *vars = NULL, *var;
1503 
1504  while ((cur = strsep(&parse, ";"))) {
1505  char *name, *val;
1506 
1507  name = val = cur;
1508  strsep(&val, "=");
1509 
1510  if (ast_strlen_zero(name) || ast_strlen_zero(val)) {
1511  continue;
1512  }
1513 
1514  name = ast_strip(name);
1515  val = ast_strip_quoted(val, "\"", "\"");
1516 
1517  if (ast_strlen_zero(name) || ast_strlen_zero(val)) {
1518  continue;
1519  }
1520 
1521  ast_debug(1, "HTTP Cookie, Name: '%s' Value: '%s'\n", name, val);
1522 
1523  var = ast_variable_new(name, val, __FILE__);
1524  var->next = vars;
1525  vars = var;
1526  }
1527 
1528  return vars;
1529 }
Definition: ast_expr2.c:325
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: main/utils.c:1639
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_variable_new(name, value, filename)
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
static const char name[]
Definition: cdr_mysql.c:74
char * strsep(char **str, const char *delims)

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 2334 of file http.c.

References __ast_http_load().

Referenced by load_module().

2335 {
2336  return __ast_http_load(1);
2337 }
static int __ast_http_load(int reload)
Definition: http.c:2077

◆ remove_excess_lws()

static void remove_excess_lws ( char *  s)
static

Definition at line 1659 of file http.c.

References ast_free, ast_malloc, ast_skip_blanks(), ast_skip_nonblanks(), and buf.

Referenced by ast_http_header_parse().

1660 {
1661  char *p, *res = s;
1662  char *buf = ast_malloc(strlen(s) + 1);
1663  char *buf_end;
1664 
1665  if (!buf) {
1666  return;
1667  }
1668 
1669  buf_end = buf;
1670 
1671  while (*s && *(s = ast_skip_blanks(s))) {
1672  p = s;
1673  s = ast_skip_nonblanks(s);
1674 
1675  if (buf_end != buf) {
1676  *buf_end++ = ' ';
1677  }
1678 
1679  memcpy(buf_end, p, s - p);
1680  buf_end += s - p;
1681  }
1682  *buf_end = '\0';
1683  /* safe since buf will always be less than or equal to res */
1684  strcpy(res, buf);
1685  ast_free(buf);
1686 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * ast_skip_nonblanks(const char *str)
Gets a pointer to first whitespace character in a string.
Definition: strings.h:200
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
#define ast_free(a)
Definition: astmm.h:182

◆ static_callback()

static int static_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_vars,
struct ast_variable headers 
)
static

Definition at line 240 of file http.c.

References ast_alloca, ast_config_AST_DATA_DIR, ast_http_error(), ast_http_ftype2mtype(), AST_HTTP_GET, AST_HTTP_HEAD, ast_http_manid_from_vars(), ast_http_request_close_on_completion(), ast_http_send(), ast_localtime(), ast_str_create, ast_str_set(), ast_strftime(), ast_strlen_zero, astman_is_authed(), len(), mtype, ast_variable::name, ast_variable::next, NULL, S_OR, and ast_variable::value.

244 {
245  char *path;
246  const char *ftype;
247  const char *mtype;
248  char wkspace[80];
249  struct stat st;
250  int len;
251  int fd;
252  struct ast_str *http_header;
253  struct timeval tv;
254  struct ast_tm tm;
255  char timebuf[80], etag[23];
256  struct ast_variable *v;
257  int not_modified = 0;
258 
259  if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) {
260  ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
261  return 0;
262  }
263 
264  /* Yuck. I'm not really sold on this, but if you don't deliver static content it
265  * makes your configuration substantially more challenging, but this seems like a
266  * rather irritating feature creep on Asterisk.
267  *
268  * XXX: It is not clear to me what this comment means or if it is any longer
269  * relevant. */
270  if (ast_strlen_zero(uri)) {
271  goto out403;
272  }
273 
274  /* Disallow any funny filenames at all (checking first character only??) */
275  if ((uri[0] < 33) || strchr("./|~@#$%^&*() \t", uri[0])) {
276  goto out403;
277  }
278 
279  if (strstr(uri, "/..")) {
280  goto out403;
281  }
282 
283  if ((ftype = strrchr(uri, '.'))) {
284  ftype++;
285  }
286 
287  if (!(mtype = ast_http_ftype2mtype(ftype))) {
288  snprintf(wkspace, sizeof(wkspace), "text/%s", S_OR(ftype, "plain"));
289  mtype = wkspace;
290  }
291 
292  /* Cap maximum length */
293  if ((len = strlen(uri) + strlen(ast_config_AST_DATA_DIR) + strlen("/static-http/") + 5) > 1024) {
294  goto out403;
295  }
296 
297  path = ast_alloca(len);
298  sprintf(path, "%s/static-http/%s", ast_config_AST_DATA_DIR, uri);
299  if (stat(path, &st)) {
300  goto out404;
301  }
302 
303  if (S_ISDIR(st.st_mode)) {
304  goto out404;
305  }
306 
307  if (strstr(path, "/private/") && !astman_is_authed(ast_http_manid_from_vars(headers))) {
308  goto out403;
309  }
310 
311  fd = open(path, O_RDONLY);
312  if (fd < 0) {
313  goto out403;
314  }
315 
316  /* make "Etag:" http header value */
317  snprintf(etag, sizeof(etag), "\"%ld\"", (long)st.st_mtime);
318 
319  /* make "Last-Modified:" http header value */
320  tv.tv_sec = st.st_mtime;
321  tv.tv_usec = 0;
322  ast_strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", ast_localtime(&tv, &tm, "GMT"));
323 
324  /* check received "If-None-Match" request header and Etag value for file */
325  for (v = headers; v; v = v->next) {
326  if (!strcasecmp(v->name, "If-None-Match")) {
327  if (!strcasecmp(v->value, etag)) {
328  not_modified = 1;
329  }
330  break;
331  }
332  }
333 
334  http_header = ast_str_create(255);
335  if (!http_header) {
337  ast_http_error(ser, 500, "Server Error", "Out of memory");
338  close(fd);
339  return 0;
340  }
341 
342  ast_str_set(&http_header, 0, "Content-type: %s\r\n"
343  "ETag: %s\r\n"
344  "Last-Modified: %s\r\n",
345  mtype,
346  etag,
347  timebuf);
348 
349  /* ast_http_send() frees http_header, so we don't need to do it before returning */
350  if (not_modified) {
351  ast_http_send(ser, method, 304, "Not Modified", http_header, NULL, 0, 1);
352  } else {
353  ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 1); /* static content flag is set */
354  }
355  close(fd);
356  return 0;
357 
358 out404:
359  ast_http_error(ser, 404, "Not Found", "The requested URL was not found on this server.");
360  return 0;
361 
362 out403:
364  ast_http_error(ser, 403, "Access Denied", "You do not have permission to access the requested URL.");
365  return 0;
366 }
struct ast_variable * next
uint32_t ast_http_manid_from_vars(struct ast_variable *headers)
Return manager id, if exist, from request headers.
Definition: http.c:217
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
Structure for variables, used for configurations and for channel variables.
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
int astman_is_authed(uint32_t ident)
Determinie if a manager session ident is authenticated.
Definition: manager.c:7551
const char * method
Definition: res_pjsip.c:4335
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
const char * mtype
Definition: http.c:148
void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser)
Request the HTTP connection be closed after this HTTP request.
Definition: http.c:836
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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, int fd, unsigned int static_content)
Generic function for sending HTTP/1.1 response.
Definition: http.c:456
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
void ast_http_error(struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
Send HTTP error message and close socket.
Definition: http.c:648
const char * ast_http_ftype2mtype(const char *ftype)
Return mime type based on extension.
Definition: http.c:203
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2343 of file http.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_free, ast_http_uri_unlink(), AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_tcptls_server_stop(), ast_tls_config::capath, ast_tls_config::certfile, ast_tls_config::cipher, ast_tls_config::enabled, http_tls_cfg, ast_tls_config::pvtfile, static_uri_enabled, and status_uri_enabled.

Referenced by load_module().

2344 {
2345  struct http_uri_redirect *redirect;
2347 
2349  if (http_tls_cfg.enabled) {
2351  }
2356 
2357  if (status_uri_enabled) {
2359  }
2360 
2361  if (static_uri_enabled) {
2363  }
2364 
2366  while ((redirect = AST_RWLIST_REMOVE_HEAD(&uri_redirects, entry))) {
2367  ast_free(redirect);
2368  }
2370 
2371  return 0;
2372 }
char * pvtfile
Definition: tcptls.h:90
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static int static_uri_enabled
Definition: http.c:142
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
static struct ast_cli_entry cli_http[]
Definition: http.c:2339
static int status_uri_enabled
Definition: http.c:143
void ast_http_uri_unlink(struct ast_http_uri *urih)
Unregister a URI handler.
Definition: http.c:705
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static struct ast_tls_config http_tls_cfg
Definition: http.c:111
static struct ast_tcptls_session_args http_desc
Definition: http.c:118
#define ast_free(a)
Definition: astmm.h:182
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:843
char * certfile
Definition: tcptls.h:89
static struct ast_http_uri static_uri
Definition: http.c:430
Definition: search.h:40
char * capath
Definition: tcptls.h:93
void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc)
Shutdown a running server if there is one.
Definition: tcptls.c:849
static struct ast_tcptls_session_args https_desc
Definition: http.c:128
static struct ast_http_uri status_uri
Definition: http.c:421
char * cipher
Definition: tcptls.h:91
int enabled
Definition: tcptls.h:88

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Built-in HTTP Server" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
static

Definition at line 2388 of file http.c.

◆ ast_http_methods_text

const struct ast_cfhttp_methods_text ast_http_methods_text[]
static

Referenced by ast_get_http_method().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2388 of file http.c.

◆ cli_http

struct ast_cli_entry cli_http[]
static
Initial value:
= {
{ .handler = handle_show_http , .summary = "Display HTTP server status" ,},
}
static char * handle_show_http(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: http.c:2279

Definition at line 2339 of file http.c.

◆ ext

const char* ext

◆ http_desc

struct ast_tcptls_session_args http_desc
static

we have up to two accepting threads, one for http, one for https

Definition at line 118 of file http.c.

◆ http_server_name

char http_server_name[MAX_SERVER_NAME_LENGTH]
static

◆ http_tls_cfg

struct ast_tls_config http_tls_cfg
static

Definition at line 111 of file http.c.

Referenced by __ast_http_load(), handle_show_http(), httpstatus_callback(), and unload_module().

◆ https_desc

struct ast_tcptls_session_args https_desc
static

Definition at line 128 of file http.c.

◆ mimetypes

struct { ... } mimetypes[]

Limit the kinds of files we're willing to serve up.

Referenced by ast_http_ftype2mtype().

◆ mtype

const char* mtype

Definition at line 148 of file http.c.

Referenced by static_callback().

◆ prefix

char prefix[MAX_PREFIX]
static

◆ session_count

int session_count = 0
static

◆ session_inactivity

int session_inactivity = DEFAULT_SESSION_INACTIVITY
static

Definition at line 107 of file http.c.

Referenced by __ast_http_load(), and httpd_helper_thread().

◆ session_keep_alive

int session_keep_alive = DEFAULT_SESSION_KEEP_ALIVE
static

Definition at line 108 of file http.c.

Referenced by __ast_http_load(), ast_http_send(), and httpd_helper_thread().

◆ session_limit

int session_limit = DEFAULT_SESSION_LIMIT
static

Definition at line 106 of file http.c.

Referenced by __ast_http_load(), and httpd_helper_thread().

◆ static_uri

struct ast_http_uri static_uri
static

Definition at line 430 of file http.c.

◆ static_uri_enabled

int static_uri_enabled
static

Definition at line 142 of file http.c.

Referenced by __ast_http_load(), and unload_module().

◆ status_uri

struct ast_http_uri status_uri
static

Definition at line 421 of file http.c.

◆ status_uri_enabled

int status_uri_enabled
static

Definition at line 143 of file http.c.

Referenced by __ast_http_load(), and unload_module().

◆ uri_redirects

struct uri_redirects uri_redirects = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ uris

struct uris uris = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

list of supported handlers