Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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  ast_http_server
 
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 HTTP_SERVER_BUCKETS   5
 Number of HTTP server buckets. More...
 
#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...
 
 AO2_STRING_FIELD_CMP_FN (ast_http_server, address)
 
 AO2_STRING_FIELD_HASH_FN (ast_http_server, address)
 
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 struct ast_http_serverhttp_server_create (const char *name, const char *address, const struct ast_sockaddr *addr)
 
static void http_server_destroy (void *obj)
 
static void http_server_discard (struct ast_http_server *server)
 Discard/Drop a HTTP server. More...
 
static struct ast_http_serverhttp_server_get (const char *name, const char *host, uint32_t port, struct ast_http_server **replace_me)
 Retrieve, or create and start a HTTP server. More...
 
static struct ast_http_serverhttp_server_get_by_addr (const char *name, const struct ast_sockaddr *addr)
 Retrieve, or create a HTTP server object by sock address. More...
 
static struct ast_http_serverhttp_server_get_by_host (const char *name, const char *host, uint32_t port)
 Retrieve, or create a HTTP server object by host. More...
 
static int http_server_start (struct ast_http_server *server)
 
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 = AST_BUILDOPT_SUM, .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 []
 
struct ast_http_serverglobal_http_server = NULL
 
static char http_server_name [MAX_SERVER_NAME_LENGTH]
 
struct ao2_containerhttp_servers = NULL
 
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 1580 of file http.c.

◆ BASIC_PREFIX

#define BASIC_PREFIX   "Basic "

Definition at line 1579 of file http.c.

◆ DEFAULT_PORT

#define DEFAULT_PORT   8088

Definition at line 69 of file http.c.

◆ 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.

◆ DEFAULT_SESSION_INACTIVITY

#define DEFAULT_SESSION_INACTIVITY   30000

(ms) Idle time waiting for data.

Definition at line 73 of file http.c.

◆ DEFAULT_SESSION_KEEP_ALIVE

#define DEFAULT_SESSION_KEEP_ALIVE   15000

(ms) Idle time between HTTP requests

Definition at line 77 of file http.c.

◆ DEFAULT_SESSION_LIMIT

#define DEFAULT_SESSION_LIMIT   100

Definition at line 71 of file http.c.

◆ DEFAULT_TLS_PORT

#define DEFAULT_TLS_PORT   8089

Definition at line 70 of file http.c.

◆ HTTP_SERVER_BUCKETS

#define HTTP_SERVER_BUCKETS   5

Number of HTTP server buckets.

Definition at line 2081 of file http.c.

◆ INITIAL_RESPONSE_BODY_BUFFER

#define INITIAL_RESPONSE_BODY_BUFFER   1024

Initial response body length.

Definition at line 92 of file http.c.

◆ 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.

◆ MAX_HTTP_LINE_LENGTH

#define MAX_HTTP_LINE_LENGTH   4096

Maximum line length for HTTP requests.

Definition at line 99 of file http.c.

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

◆ MAX_PREFIX

#define MAX_PREFIX   80

Definition at line 68 of file http.c.

◆ 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.

◆ 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.

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

442 {
443 /*! TRUE if the HTTP request has a body. */
444 HTTP_FLAG_HAS_BODY = (1 << 0),
445 /*! TRUE if the HTTP request body has been read. */
446 HTTP_FLAG_BODY_READ = (1 << 1),
447 /*! TRUE if the HTTP request must close when completed. */
449};
@ HTTP_FLAG_BODY_READ
Definition: http.c:446
@ HTTP_FLAG_CLOSE_ON_COMPLETION
Definition: http.c:448
@ HTTP_FLAG_HAS_BODY
Definition: http.c:444

Function Documentation

◆ __ast_http_load()

static int __ast_http_load ( int  reload)
static

Definition at line 2367 of file http.c.

2368{
2369 struct ast_config *cfg;
2370 struct ast_variable *v;
2371 int enabled = 0;
2372 int new_static_uri_enabled = 0;
2373 int new_status_uri_enabled = 1; /* Default to enabled for BC */
2374 char newprefix[MAX_PREFIX] = "";
2375 char server_name[MAX_SERVER_NAME_LENGTH];
2376 struct http_uri_redirect *redirect;
2377 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2378 uint32_t bindport = DEFAULT_PORT;
2379 int http_tls_was_enabled = 0;
2380 char *bindaddr = NULL;
2381
2382 cfg = ast_config_load2("http.conf", "http", config_flags);
2383 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
2384 return 0;
2385 }
2386
2387 /* Even if the http.conf hasn't been updated, the TLS certs/keys may have been */
2388 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2391 }
2392 return 0;
2393 }
2394
2395 http_tls_was_enabled = (reload && http_tls_cfg.enabled);
2396
2398
2401
2404
2407
2408 /* Apply modern intermediate settings according to the Mozilla OpSec team as of July 30th, 2015 but disable TLSv1 */
2410
2412 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");
2413
2415 while ((redirect = AST_RWLIST_REMOVE_HEAD(&uri_redirects, entry))) {
2416 ast_free(redirect);
2417 }
2419
2421
2425
2426 snprintf(server_name, sizeof(server_name), "Asterisk/%s", ast_get_version());
2427
2428 v = ast_variable_browse(cfg, "general");
2429 for (; v; v = v->next) {
2430 /* read tls config options while preventing unsupported options from being set */
2431 if (strcasecmp(v->name, "tlscafile")
2432 && strcasecmp(v->name, "tlscapath")
2433 && strcasecmp(v->name, "tlscadir")
2434 && strcasecmp(v->name, "tlsverifyclient")
2435 && strcasecmp(v->name, "tlsdontverifyserver")
2436 && strcasecmp(v->name, "tlsclientmethod")
2437 && strcasecmp(v->name, "sslclientmethod")
2439 continue;
2440 }
2441
2442 if (!strcasecmp(v->name, "servername")) {
2443 if (!ast_strlen_zero(v->value)) {
2444 ast_copy_string(server_name, v->value, sizeof(server_name));
2445 } else {
2446 server_name[0] = '\0';
2447 }
2448 } else if (!strcasecmp(v->name, "enabled")) {
2449 enabled = ast_true(v->value);
2450 } else if (!strcasecmp(v->name, "enablestatic") || !strcasecmp(v->name, "enable_static")) {
2451 new_static_uri_enabled = ast_true(v->value);
2452 } else if (!strcasecmp(v->name, "enable_status")) {
2453 new_status_uri_enabled = ast_true(v->value);
2454 } else if (!strcasecmp(v->name, "bindport")) {
2456 &bindport, DEFAULT_PORT, 0, 65535)) {
2457 ast_log(LOG_WARNING, "Invalid port %s specified. Using default port %" PRId32 "\n",
2458 v->value, DEFAULT_PORT);
2459 }
2460 } else if (!strcasecmp(v->name, "bindaddr")) {
2462 } else if (!strcasecmp(v->name, "prefix")) {
2463 if (!ast_strlen_zero(v->value)) {
2464 newprefix[0] = '/';
2465 ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
2466 } else {
2467 newprefix[0] = '\0';
2468 }
2469 } else if (!strcasecmp(v->name, "redirect")) {
2470 add_redirect(v->value);
2471 } else if (!strcasecmp(v->name, "sessionlimit")) {
2473 &session_limit, DEFAULT_SESSION_LIMIT, 1, INT_MAX)) {
2474 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2475 v->name, v->value, v->lineno);
2476 }
2477 } else if (!strcasecmp(v->name, "session_inactivity")) {
2480 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2481 v->name, v->value, v->lineno);
2482 }
2483 } else if (!strcasecmp(v->name, "session_keep_alive")) {
2484 if (sscanf(v->value, "%30d", &session_keep_alive) != 1
2485 || session_keep_alive < 0) {
2487 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2488 v->name, v->value, v->lineno);
2489 }
2490 } else {
2491 ast_log(LOG_WARNING, "Ignoring unknown option '%s' in http.conf\n", v->name);
2492 }
2493 }
2494
2495 ast_config_destroy(cfg);
2496
2497 if (strcmp(prefix, newprefix)) {
2498 ast_copy_string(prefix, newprefix, sizeof(prefix));
2499 }
2500
2501 ast_copy_string(http_server_name, server_name, sizeof(http_server_name));
2502
2503 if (enabled) {
2504 http_server_get("http server", bindaddr, bindport, &global_http_server);
2505 } else if (global_http_server) {
2508 }
2509
2510 /* When no specific TLS bindaddr is specified, we just use
2511 * the non-TLS bindaddress here.
2512 */
2515
2517 /* Of course, we can't use the same port though.
2518 * Since no bind address was specified, we just use the
2519 * default TLS port
2520 */
2522 }
2523
2524 if (http_tls_was_enabled && !http_tls_cfg.enabled) {
2527 /* We can get here either because a TLS-specific address was specified
2528 * or because we copied the non-TLS address here. In the case where
2529 * we read an explicit address from the config, there may have been
2530 * no port specified, so we'll just use the default TLS port.
2531 */
2534 }
2537 }
2538 }
2539
2540 if (static_uri_enabled && !new_static_uri_enabled) {
2542 } else if (!static_uri_enabled && new_static_uri_enabled) {
2544 }
2545
2546 static_uri_enabled = new_static_uri_enabled;
2547
2548 if (status_uri_enabled && !new_status_uri_enabled) {
2550 } else if (!status_uri_enabled && new_status_uri_enabled) {
2552 }
2553
2554 status_uri_enabled = new_status_uri_enabled;
2555
2556 return 0;
2557}
const char * ast_get_version(void)
Retrieve the Asterisk version string.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
struct ast_sockaddr bindaddr
Definition: chan_ooh323.c:353
static int enabled
Definition: dnsmgr.c:91
#define DEFAULT_PORT
Definition: http.c:69
static struct ast_tls_config http_tls_cfg
Definition: http.c:111
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:2025
int ast_http_uri_link(struct ast_http_uri *urih)
Link the new uri into the list.
Definition: http.c:676
static int status_uri_enabled
Definition: http.c:146
static char prefix[MAX_PREFIX]
Definition: http.c:144
static int session_inactivity
Definition: http.c:107
#define DEFAULT_SESSION_INACTIVITY
Definition: http.c:73
static struct ast_http_uri status_uri
Definition: http.c:424
static void http_server_discard(struct ast_http_server *server)
Discard/Drop a HTTP server.
Definition: http.c:2170
#define DEFAULT_SESSION_KEEP_ALIVE
Definition: http.c:77
#define DEFAULT_TLS_PORT
Definition: http.c:70
void ast_http_uri_unlink(struct ast_http_uri *urih)
Unregister a URI handler.
Definition: http.c:708
static struct ast_http_uri static_uri
Definition: http.c:433
static struct ast_http_server * http_server_get(const char *name, const char *host, uint32_t port, struct ast_http_server **replace_me)
Retrieve, or create and start a HTTP server.
Definition: http.c:2280
static struct ast_tcptls_session_args https_desc
Definition: http.c:131
static int static_uri_enabled
Definition: http.c:145
static int session_keep_alive
Definition: http.c:108
#define MAX_PREFIX
Definition: http.c:68
struct ast_http_server * global_http_server
Definition: http.c:129
#define MAX_SERVER_NAME_LENGTH
Definition: http.c:79
static int session_limit
Definition: http.c:106
#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:3321
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
Definition: main/config.c:3827
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
#define LOG_WARNING
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:844
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:517
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:167
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition: netsock2.h:127
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition: netsock2.h:138
static int reload(void)
#define NULL
Definition: resample.c:96
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Structure used to handle boolean flags.
Definition: utils.h:199
struct ast_tcptls_session_args args
Definition: http.c:121
struct ast_sockaddr local_address
Definition: tcptls.h:131
struct ast_tls_config * tls_cfg
Definition: tcptls.h:135
int enabled
Definition: tcptls.h:89
char * certfile
Definition: tcptls.h:90
char * cipher
Definition: tcptls.h:92
char * pvtfile
Definition: tcptls.h:91
char * capath
Definition: tcptls.h:94
struct ast_flags flags
Definition: tcptls.h:95
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
Definition: search.h:40
#define AST_CERTFILE
Definition: tcptls.h:63
void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc)
Shutdown a running server if there is one.
Definition: tcptls.c:918
int ast_ssl_setup(struct ast_tls_config *cfg)
Set up an SSL server.
Definition: tcptls.c:570
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:753
@ AST_SSL_SERVER_CIPHER_ORDER
Definition: tcptls.h:79
@ AST_SSL_DISABLE_TLSV1
Definition: tcptls.h:81
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:944
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ast_tcptls_session_args::accept_fd, add_redirect(), ast_http_server::args, 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_set_port, ast_sockaddr_setnull(), AST_SSL_DISABLE_TLSV1, AST_SSL_SERVER_CIPHER_ORDER, ast_ssl_setup(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_tcptls_server_start(), ast_tcptls_server_stop(), ast_tls_read_conf(), ast_true(), ast_variable_browse(), bindaddr, 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, global_http_server, http_server_discard(), http_server_get(), http_server_name, http_tls_cfg, https_desc, 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, reload(), session_inactivity, session_keep_alive, session_limit, static_uri, static_uri_enabled, status_uri, status_uri_enabled, ast_tcptls_session_args::tls_cfg, and ast_variable::value.

Referenced by load_module(), and reload_module().

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2682 of file http.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2682 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 2025 of file http.c.

2026{
2027 char *target, *dest;
2028 struct http_uri_redirect *redirect, *cur;
2029 unsigned int target_len;
2030 unsigned int total_len;
2031 size_t dest_len;
2032
2035 target = strsep(&dest, " ");
2037 target = strsep(&target, " "); /* trim trailing whitespace */
2038
2039 if (!dest) {
2040 ast_log(LOG_WARNING, "Invalid redirect '%s'\n", value);
2041 return;
2042 }
2043
2044 target_len = strlen(target) + 1;
2045 dest_len = strlen(dest) + 1;
2046 total_len = sizeof(*redirect) + target_len + dest_len;
2047
2048 if (!(redirect = ast_calloc(1, total_len))) {
2049 return;
2050 }
2051 redirect->dest = redirect->target + target_len;
2052 strcpy(redirect->target, target);
2053 ast_copy_string(redirect->dest, dest, dest_len);
2054
2056
2057 target_len--; /* So we can compare directly with strlen() */
2059 || strlen(AST_RWLIST_FIRST(&uri_redirects)->target) <= target_len ) {
2062
2063 return;
2064 }
2065
2067 if (AST_RWLIST_NEXT(cur, entry)
2068 && strlen(AST_RWLIST_NEXT(cur, entry)->target) <= target_len ) {
2071 return;
2072 }
2073 }
2074
2076
2078}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
char * strsep(char **str, const char *delims)
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:452
#define AST_RWLIST_INSERT_AFTER
Definition: linkedlists.h:702
#define AST_RWLIST_NEXT
Definition: linkedlists.h:441
#define AST_RWLIST_FIRST
Definition: linkedlists.h:423
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:718
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
char * dest
Definition: http.c:174
char target[0]
Definition: http.c:175
int value
Definition: syslog.c:37

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(), http_uri_redirect::target, and value.

Referenced by __ast_http_load().

◆ AO2_STRING_FIELD_CMP_FN()

AO2_STRING_FIELD_CMP_FN ( ast_http_server  ,
address   
)

◆ AO2_STRING_FIELD_HASH_FN()

AO2_STRING_FIELD_HASH_FN ( ast_http_server  ,
address   
)

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

194{
195 int x;
196
197 for (x = 0; x < ARRAY_LEN(ast_http_methods_text); x++) {
199 return ast_http_methods_text[x].text;
200 }
201 }
202
203 return NULL;
204}
static const struct ast_cfhttp_methods_text ast_http_methods_text[]
const char * method
Definition: res_pjsip.c:1279
const char * text
Definition: http.c:182
#define ARRAY_LEN(a)
Definition: utils.h:666

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

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

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

628{
629 int status_code = 401;
630 char *status_title = "Unauthorized";
631 struct ast_str *http_header_data = ast_str_create(DEFAULT_RESPONSE_HEADER_LENGTH);
632
633 if (http_header_data) {
634 ast_str_set(&http_header_data,
635 0,
636 "WWW-authenticate: Digest algorithm=MD5, realm=\"%s\", nonce=\"%08lx\", qop=\"auth\", opaque=\"%08lx\"%s\r\n"
637 "Content-type: text/html\r\n",
638 realm ? realm : "Asterisk",
639 nonce,
640 opaque,
641 stale ? ", stale=true" : "");
642 }
643
645 status_code,
646 status_title,
647 http_header_data,
648 text);
649}
char * text
Definition: app_queue.c:1639
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:570
#define DEFAULT_RESPONSE_HEADER_LENGTH
Definition: http.c:81
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
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:1113
Support for dynamic strings.
Definition: strings.h:623

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

Referenced by auth_http_callback().

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

1123{
1125
1126 request = ser->private_data;
1129 /* No body to read or it has already been read. */
1130 return 0;
1131 }
1133
1134 ast_debug(1, "HTTP discarding unused request body\n");
1135
1136 ast_assert(request->body_length != 0);
1137 if (0 < request->body_length) {
1138 if (http_body_discard_contents(ser, request->body_length, "body")) {
1140 return -1;
1141 }
1142 return 0;
1143 }
1144
1145 /* parse chunked-body */
1146 for (;;) {
1147 int length;
1148
1149 length = http_body_get_chunk_length(ser);
1150 if (length < 0) {
1152 return -1;
1153 }
1154 if (length == 0) {
1155 /* parsed last-chunk */
1156 break;
1157 }
1158
1159 if (http_body_discard_contents(ser, length, "chunk-data")
1162 return -1;
1163 }
1164 }
1165
1166 /* Read and discard any trailer entity-header lines. */
1169 return -1;
1170 }
1171 return 0;
1172}
static int request(void *obj)
Definition: chan_pjsip.c:2601
static int http_body_discard_chunk_trailer_headers(struct ast_tcptls_session_instance *ser)
Definition: http.c:1102
static int http_body_discard_contents(struct ast_tcptls_session_instance *ser, int length, const char *what_getting)
Definition: http.c:966
static int http_body_check_chunk_sync(struct ast_tcptls_session_instance *ser)
Definition: http.c:1071
static int http_body_get_chunk_length(struct ast_tcptls_session_instance *ser)
Definition: http.c:1043
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_debug, ast_set_flag, ast_test_flag, 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().

◆ 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.

Definition at line 901 of file http.c.

902{
904
905 request = ser->private_data;
908 /* No body to read. */
909 return;
910 }
912 if (!read_success) {
914 }
915}

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

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

572{
573 char server_name[MAX_SERVER_NAME_LENGTH];
574 struct ast_str *server_address = ast_str_create(MAX_SERVER_NAME_LENGTH);
576
577 if (!http_header_data || !server_address || !out) {
578 ast_free(http_header_data);
579 ast_free(server_address);
580 ast_free(out);
581 if (ser) {
582 ast_debug(1, "HTTP closing session. OOM.\n");
584 }
585 return;
586 }
587
589 ast_xml_escape(http_server_name, server_name, sizeof(server_name));
590 ast_str_set(&server_address,
591 0,
592 "<address>%s</address>\r\n",
593 server_name);
594 }
595
597 0,
598 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
599 "<html><head>\r\n"
600 "<title>%d %s</title>\r\n"
601 "</head><body>\r\n"
602 "<h1>%s</h1>\r\n"
603 "<p>%s</p>\r\n"
604 "<hr />\r\n"
605 "%s"
606 "</body></html>\r\n",
607 status_code,
608 status_title,
609 status_title,
610 text ? text : "",
611 ast_str_buffer(server_address));
612
613 ast_free(server_address);
614
615 ast_http_send(ser,
617 status_code,
618 status_title,
619 http_header_data,
620 out,
621 0,
622 0);
623}
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:459
#define INITIAL_RESPONSE_BODY_BUFFER
Definition: http.c:92
@ AST_HTTP_UNKNOWN
Definition: http.h:59
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
void ast_tcptls_close_session_file(struct ast_tcptls_session_instance *tcptls_session)
Closes a tcptls session instance's file and/or file descriptor. The tcptls_session will be set to NUL...
Definition: tcptls.c:908
FILE * out
Definition: utils/frame.c:33
int ast_xml_escape(const char *string, char *outbuf, size_t buflen)
Escape reserved characters for use in XML.
Definition: utils.c:864

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, out, and text.

Referenced by ast_http_auth(), and ast_http_error().

◆ ast_http_error()

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

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

207{
208 int x;
209
210 if (ftype) {
211 for (x = 0; x < ARRAY_LEN(mimetypes); x++) {
212 if (!strcasecmp(ftype, mimetypes[x].ext)) {
213 return mimetypes[x].mtype;
214 }
215 }
216 }
217 return NULL;
218}
static struct @359 mimetypes[]
Limit the kinds of files we're willing to serve up.
const char * ext
Definition: http.c:150

References ARRAY_LEN, ext, mimetypes, and NULL.

Referenced by build_profile(), and static_callback().

◆ 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.
Return values
NULLif no supported HTTP auth headers present.
Since
12

Definition at line 1582 of file http.c.

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

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, strsep(), and ast_variable::value.

Referenced by authenticate_user(), and http_callback().

◆ 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)
Return values
NULLon failure
Note
Since returned ptr is malloc'd, it should be free'd by caller

Definition at line 1184 of file http.c.

1186{
1188 int content_length;
1189 int bufsize;
1190 char *buf;
1191
1192 request = ser->private_data;
1193 if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)) {
1194 /* no content - not an error */
1195 return NULL;
1196 }
1198 /* Already read the body. Cannot read again. Assume no content. */
1199 ast_assert(0);
1200 return NULL;
1201 }
1203
1204 ast_debug(2, "HTTP consuming request body\n");
1205
1206 ast_assert(request->body_length != 0);
1207 if (0 < request->body_length) {
1208 /* handle regular non-chunked content */
1209 content_length = request->body_length;
1210 if (content_length > MAX_CONTENT_LENGTH) {
1211 ast_log(LOG_WARNING, "Excessively long HTTP content. (%d > %d)\n",
1212 content_length, MAX_CONTENT_LENGTH);
1214 errno = EFBIG;
1215 return NULL;
1216 }
1217 buf = ast_malloc(content_length + 1);
1218 if (!buf) {
1219 /* Malloc sets ENOMEM */
1221 return NULL;
1222 }
1223
1224 if (http_body_read_contents(ser, buf, content_length, "body")) {
1226 errno = EIO;
1227 ast_free(buf);
1228 return NULL;
1229 }
1230
1231 buf[content_length] = 0;
1232 *return_length = content_length;
1233 return buf;
1234 }
1235
1236 /* pre-allocate buffer */
1237 bufsize = 250;
1238 buf = ast_malloc(bufsize);
1239 if (!buf) {
1241 return NULL;
1242 }
1243
1244 /* parse chunked-body */
1245 content_length = 0;
1246 for (;;) {
1247 int chunk_length;
1248
1249 chunk_length = http_body_get_chunk_length(ser);
1250 if (chunk_length < 0) {
1252 errno = EIO;
1253 ast_free(buf);
1254 return NULL;
1255 }
1256 if (chunk_length == 0) {
1257 /* parsed last-chunk */
1258 break;
1259 }
1260 if (content_length + chunk_length > MAX_CONTENT_LENGTH) {
1262 "Excessively long HTTP accumulated chunked body. (%d + %d > %d)\n",
1263 content_length, chunk_length, MAX_CONTENT_LENGTH);
1265 errno = EFBIG;
1266 ast_free(buf);
1267 return NULL;
1268 }
1269
1270 /* insure buffer is large enough +1 */
1271 if (content_length + chunk_length >= bufsize) {
1272 char *new_buf;
1273
1274 /* Increase bufsize until it can handle the expected data. */
1275 do {
1276 bufsize *= 2;
1277 } while (content_length + chunk_length >= bufsize);
1278
1279 new_buf = ast_realloc(buf, bufsize);
1280 if (!new_buf) {
1282 ast_free(buf);
1283 return NULL;
1284 }
1285 buf = new_buf;
1286 }
1287
1288 if (http_body_read_contents(ser, buf + content_length, chunk_length, "chunk-data")
1291 errno = EIO;
1292 ast_free(buf);
1293 return NULL;
1294 }
1295 content_length += chunk_length;
1296 }
1297
1298 /*
1299 * Read and discard any trailer entity-header lines
1300 * which we don't care about.
1301 *
1302 * XXX In the future we may need to add the trailer headers
1303 * to the passed in headers list rather than discarding them.
1304 */
1307 errno = EIO;
1308 ast_free(buf);
1309 return NULL;
1310 }
1311
1312 buf[content_length] = 0;
1313 *return_length = content_length;
1314 return buf;
1315}
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:226
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define MAX_CONTENT_LENGTH
Definition: http.c:85
static int http_body_read_contents(struct ast_tcptls_session_instance *ser, char *buf, int length, const char *what_getting)
Definition: http.c:930
int errno

References ast_assert, ast_debug, ast_free, ast_log, ast_malloc, ast_realloc, ast_set_flag, ast_test_flag, buf, errno, 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().

◆ ast_http_get_cookies()

struct ast_variable * ast_http_get_cookies ( struct ast_variable headers)

Get cookie from Request headers.

Definition at line 1535 of file http.c.

1536{
1537 struct ast_variable *v, *cookies = NULL;
1538
1539 for (v = headers; v; v = v->next) {
1540 if (!strcasecmp(v->name, "Cookie")) {
1541 ast_variables_destroy(cookies);
1542 cookies = parse_cookies(v->value);
1543 }
1544 }
1545 return cookies;
1546}
static struct ast_variable * parse_cookies(const char *cookies)
Definition: http.c:1501
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262

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

◆ 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
Return values
NULLon error, if no content, or if different content type.
Since
12

Definition at line 1317 of file http.c.

1319{
1320 int content_length = 0;
1321 struct ast_json *body;
1322 RAII_VAR(char *, buf, NULL, ast_free);
1323 RAII_VAR(char *, type, get_content_type(headers), ast_free);
1324
1325 /* Use errno to distinguish errors from no body */
1326 errno = 0;
1327
1328 if (ast_strlen_zero(type) || strcasecmp(type, "application/json")) {
1329 /* Content type is not JSON. Don't read the body. */
1330 return NULL;
1331 }
1332
1333 buf = ast_http_get_contents(&content_length, ser, headers);
1334 if (!buf || !content_length) {
1335 /*
1336 * errno already set
1337 * or it is not an error to have zero content
1338 */
1339 return NULL;
1340 }
1341
1342 body = ast_json_load_buf(buf, content_length, NULL);
1343 if (!body) {
1344 /* Failed to parse JSON; treat as an I/O error */
1345 errno = EIO;
1346 return NULL;
1347 }
1348
1349 return body;
1350}
static const char type[]
Definition: chan_ooh323.c:109
static char * get_content_type(struct ast_variable *headers)
Retrieves the content type specified in the "Content-Type" header.
Definition: http.c:765
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:1184
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:585
Abstract JSON element (object, array, string, int, ...).
#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:941

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

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

1358{
1359 int content_length = 0;
1360 struct ast_variable *v, *post_vars=NULL, *prev = NULL;
1361 char *var, *val;
1362 RAII_VAR(char *, buf, NULL, ast_free);
1363 RAII_VAR(char *, type, get_content_type(headers), ast_free);
1364
1365 /* Use errno to distinguish errors from no params */
1366 errno = 0;
1367
1368 if (ast_strlen_zero(type) ||
1369 strcasecmp(type, "application/x-www-form-urlencoded")) {
1370 /* Content type is not form data. Don't read the body. */
1371 return NULL;
1372 }
1373
1374 buf = ast_http_get_contents(&content_length, ser, headers);
1375 if (!buf || !content_length) {
1376 /*
1377 * errno already set
1378 * or it is not an error to have zero content
1379 */
1380 return NULL;
1381 }
1382
1383 while ((val = strsep(&buf, "&"))) {
1384 var = strsep(&val, "=");
1385 if (val) {
1387 } else {
1388 val = "";
1389 }
1391 if ((v = ast_variable_new(var, val, ""))) {
1392 if (post_vars) {
1393 prev->next = v;
1394 } else {
1395 post_vars = v;
1396 }
1397 prev = v;
1398 }
1399 }
1400
1401 return post_vars;
1402}
#define var
Definition: ast_expr2f.c:605
#define ast_variable_new(name, value, filename)
Definition: ast_expr2.c:325
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Definition: utils.c:762
const struct ast_flags ast_uri_http_legacy
Definition: utils.c:720

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

◆ 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
Return values
0if the name and expected name do not match
-1if the value and expected value do not match
1if the both the name and value match their expected value
Since
13

Definition at line 1713 of file http.c.

1715{
1716 if (strcasecmp(name, expected_name)) {
1717 /* no value to validate if names don't match */
1718 return 0;
1719 }
1720
1721 if (strcasecmp(value, expected_value)) {
1722 ast_log(LOG_ERROR, "Invalid header value - expected %s "
1723 "received %s", value, expected_value);
1724 return -1;
1725 }
1726 return 1;
1727}
static const char name[]
Definition: format_mp3.c:68
#define LOG_ERROR

References ast_log, LOG_ERROR, name, and value.

Referenced by websocket_client_handshake_get_response().

◆ 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)
Return values
0if the name and expected name do not match
-1if the value and is not in the expected value
1if the name matches expected name and value is in expected value
Since
13

Definition at line 1729 of file http.c.

1731{
1732 if (strcasecmp(name, expected_name)) {
1733 /* no value to validate if names don't match */
1734 return 0;
1735 }
1736
1737 if (!strcasestr(expected_value, value)) {
1738 ast_log(LOG_ERROR, "Header '%s' - could not locate '%s' "
1739 "in '%s'\n", name, value, expected_value);
1740 return -1;
1741
1742 }
1743 return 1;
1744}
char * strcasestr(const char *, const char *)

References ast_log, LOG_ERROR, name, strcasestr(), and value.

Referenced by websocket_client_handshake_get_response().

◆ 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
[out]nameheader name
[out]valueheader value
Return values
-1if buf is empty
0if buf could be separated into name and value
1if name or value portion don't exist
Since
13

Definition at line 1691 of file http.c.

1692{
1694 if (ast_strlen_zero(buf)) {
1695 return -1;
1696 }
1697
1698 *value = buf;
1699 *name = strsep(value, ":");
1700 if (!*value) {
1701 return 1;
1702 }
1703
1706 return 1;
1707 }
1708
1710 return 0;
1711}
static void remove_excess_lws(char *s)
Definition: http.c:1662
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:186

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

Referenced by websocket_client_handshake_get_response().

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

221{
222 uint32_t mngid = 0;
223 struct ast_variable *v, *cookies;
224
225 cookies = ast_http_get_cookies(headers);
226 for (v = cookies; v; v = v->next) {
227 if (!strcasecmp(v->name, "mansession_id")) {
228 sscanf(v->value, "%30x", &mngid);
229 break;
230 }
231 }
232 ast_variables_destroy(cookies);
233 return mngid;
234}
struct ast_variable * ast_http_get_cookies(struct ast_variable *headers)
Get cookie from Request headers.
Definition: http.c:1535

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

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

237{
238 if (buf) {
240 }
241}
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

References ast_copy_string(), buf, len(), and prefix.

◆ 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.

Definition at line 840 of file http.c.

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

◆ 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
Return values
-1if version didn't match or status code conversion fails.
Returns
status code (>0)
Since
13

Definition at line 1639 of file http.c.

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

References ast_log, buf, LOG_ERROR, and version.

Referenced by websocket_client_handshake_get_response().

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

463{
464 struct timeval now = ast_tvnow();
465 struct ast_tm tm;
466 char timebuf[80];
467 char buf[256];
468 int len;
469 int content_length = 0;
470 int close_connection;
471 struct ast_str *server_header_field = ast_str_create(MAX_SERVER_NAME_LENGTH);
472 int send_content;
473
474 if (!ser || !server_header_field) {
475 /* The connection is not open. */
476 ast_free(http_header);
477 ast_free(out);
478 ast_free(server_header_field);
479 return;
480 }
481
483 ast_str_set(&server_header_field,
484 0,
485 "Server: %s\r\n",
487 }
488
489 /*
490 * We shouldn't be sending non-final status codes to this
491 * function because we may close the connection before
492 * returning.
493 */
494 ast_assert(200 <= status_code);
495
496 if (session_keep_alive <= 0) {
497 close_connection = 1;
498 } else {
500
501 request = ser->private_data;
502 if (!request
504 || ast_http_body_discard(ser)) {
505 close_connection = 1;
506 } else {
507 close_connection = 0;
508 }
509 }
510
511 ast_strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", ast_localtime(&now, &tm, "GMT"));
512
513 /* calc content length */
514 if (out) {
515 content_length += ast_str_strlen(out);
516 }
517
518 if (fd) {
519 content_length += lseek(fd, 0, SEEK_END);
520 lseek(fd, 0, SEEK_SET);
521 }
522
523 send_content = method != AST_HTTP_HEAD || status_code >= 400;
524
525 /* send http header */
527 "HTTP/1.1 %d %s\r\n"
528 "%s"
529 "Date: %s\r\n"
530 "%s"
531 "%s"
532 "%s"
533 "Content-Length: %d\r\n"
534 "\r\n"
535 "%s",
536 status_code, status_title ? status_title : "OK",
537 ast_str_buffer(server_header_field),
538 timebuf,
539 close_connection ? "Connection: close\r\n" : "",
540 static_content ? "" : "Cache-Control: no-cache, no-store\r\n",
541 http_header ? ast_str_buffer(http_header) : "",
542 content_length,
543 send_content && out && ast_str_strlen(out) ? ast_str_buffer(out) : ""
544 ) <= 0) {
545 ast_debug(1, "ast_iostream_printf() failed: %s\n", strerror(errno));
546 close_connection = 1;
547 } else if (send_content && fd) {
548 /* send file content */
549 while ((len = read(fd, buf, sizeof(buf))) > 0) {
550 if (ast_iostream_write(ser->stream, buf, len) != len) {
551 ast_debug(1, "ast_iostream_write() failed: %s\n", strerror(errno));
552 close_connection = 1;
553 break;
554 }
555 }
556 }
557
558 ast_free(http_header);
559 ast_free(out);
560 ast_free(server_header_field);
561
562 if (close_connection) {
563 ast_debug(1, "HTTP closing session. status_code:%d\n", status_code);
565 } else {
566 ast_debug(1, "HTTP keeping session open. status_code:%d\n", status_code);
567 }
568}
int ast_http_body_discard(struct ast_tcptls_session_instance *ser)
Read and discard any unread HTTP request body.
Definition: http.c:1122
@ AST_HTTP_HEAD
Definition: http.h:62
ssize_t ast_iostream_printf(struct ast_iostream *stream, const char *format,...)
Write a formatted string to an iostream.
Definition: iostream.c:491
ssize_t ast_iostream_write(struct ast_iostream *stream, const void *buffer, size_t count)
Write data to an iostream.
Definition: iostream.c:374
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
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
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
struct ast_iostream * stream
Definition: tcptls.h:161
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

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_FLAG_CLOSE_ON_COMPLETION, http_server_name, len(), MAX_SERVER_NAME_LENGTH, method, out, 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(), phoneprov_callback(), static_callback(), and websocket_bad_request().

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

677{
678 struct ast_http_uri *uri;
679 int len = strlen(urih->uri);
680
682
683 urih->prefix = prefix;
684
685 if ( AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len ) {
688 return 0;
689 }
690
692 if (AST_RWLIST_NEXT(uri, entry) &&
693 strlen(AST_RWLIST_NEXT(uri, entry)->uri) <= len) {
696
697 return 0;
698 }
699 }
700
702
704
705 return 0;
706}
Definition of a URI handler.
Definition: http.h:102
const char * prefix
Definition: http.h:106
const char * uri
Definition: http.h:105
Definition: http.c:141

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

◆ ast_http_uri_unlink()

void ast_http_uri_unlink ( struct ast_http_uri urih)

Unregister a URI handler.

Definition at line 708 of file http.c.

709{
713}
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:885

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

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

716{
717 struct ast_http_uri *urih;
720 if (!strcmp(urih->key, key)) {
722 if (urih->dmallocd) {
723 ast_free(urih->data);
724 }
725 if (urih->mallocd) {
726 ast_free(urih);
727 }
728 }
729 }
732}
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
unsigned int dmallocd
Definition: http.h:112
void * data
Definition: http.h:116
const char * key
Definition: http.h:118
unsigned int mallocd
Definition: http.h:110

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

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 2682 of file http.c.

◆ auth_create()

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

Definition at line 1548 of file http.c.

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

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

Referenced by ast_http_get_auth().

◆ chunked_atoh()

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

Definition at line 989 of file http.c.

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

References c, len(), and value.

Referenced by http_body_get_chunk_length().

◆ get_content_length()

static int get_content_length ( struct ast_variable headers)
static

Returns the value of the Content-Length header.

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

Definition at line 790 of file http.c.

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

References get_header().

Referenced by http_request_tracking_setup().

◆ 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.
Returns
the content type/subtype
Return values
NULLif the header is not found.

Definition at line 765 of file http.c.

766{
767 const char *content_type = get_header(headers, "Content-Type");
768 const char *param;
769 size_t size;
770
771 if (!content_type) {
772 return NULL;
773 }
774
775 param = strchr(content_type, ';');
776 size = param ? param - content_type : strlen(content_type);
777
778 return ast_strndup(content_type, size);
779}
#define ast_strndup(str, len)
A wrapper for strndup()
Definition: astmm.h:256

References ast_strndup, get_header(), and NULL.

Referenced by ast_http_get_json(), and ast_http_get_post_vars().

◆ 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.
Return values
NULLif header is not present.

Definition at line 742 of file http.c.

743{
744 struct ast_variable *v;
745
746 for (v = headers; v; v = v->next) {
747 if (!strcasecmp(v->name, field_name)) {
748 return v->value;
749 }
750 }
751 return NULL;
752}

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

◆ 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.
Returns
string Value of the Transfer-Encoding header.
Return values
NULLif header is not present.

Definition at line 815 of file http.c.

816{
817 return get_header(headers, "Transfer-Encoding");
818}

References get_header().

Referenced by http_request_tracking_setup(), and httpd_process_request().

◆ handle_show_http()

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

Definition at line 2559 of file http.c.

2560{
2561 struct ast_http_uri *urih;
2562 struct http_uri_redirect *redirect;
2563
2564 switch (cmd) {
2565 case CLI_INIT:
2566 e->command = "http show status";
2567 e->usage =
2568 "Usage: http show status\n"
2569 " Lists status of internal HTTP engine\n";
2570 return NULL;
2571 case CLI_GENERATE:
2572 return NULL;
2573 }
2574
2575 if (a->argc != 3) {
2576 return CLI_SHOWUSAGE;
2577 }
2578 ast_cli(a->fd, "HTTP Server Status:\n");
2579 ast_cli(a->fd, "Prefix: %s\n", prefix);
2580 ast_cli(a->fd, "Server: %s\n", http_server_name);
2581 if (!global_http_server) {
2582 ast_cli(a->fd, "Server Disabled\n\n");
2583 } else {
2584 ast_cli(a->fd, "Server Enabled and Bound to %s\n\n",
2586 if (http_tls_cfg.enabled) {
2587 ast_cli(a->fd, "HTTPS Server Enabled and Bound to %s\n\n",
2589 }
2590 }
2591
2592 ast_cli(a->fd, "Enabled URI's:\n");
2594 if (AST_RWLIST_EMPTY(&uris)) {
2595 ast_cli(a->fd, "None.\n");
2596 } else {
2598 ast_cli(a->fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
2599 }
2601
2602 ast_cli(a->fd, "\nEnabled Redirects:\n");
2605 ast_cli(a->fd, " %s => %s\n", redirect->target, redirect->dest);
2607 ast_cli(a->fd, " None.\n");
2608 }
2610
2611 return CLI_SUCCESS;
2612}
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
unsigned int has_subtree
Definition: http.h:108
const char * description
Definition: http.h:104
struct ast_sockaddr old_address
Definition: tcptls.h:132
static struct test_val a

References a, ast_http_server::args, ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, 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, global_http_server, ast_http_uri::has_subtree, http_server_name, http_tls_cfg, https_desc, NULL, ast_tcptls_session_args::old_address, prefix, http_uri_redirect::target, ast_http_uri::uri, and ast_cli_entry::usage.

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

1406{
1407 char *c;
1408 int res = 0;
1409 char *params = uri;
1410 struct ast_http_uri *urih = NULL;
1411 int l;
1412 struct ast_variable *get_vars = NULL, *v, *prev = NULL;
1413 struct http_uri_redirect *redirect;
1414
1415 ast_debug(2, "HTTP Request URI is %s \n", uri);
1416
1417 strsep(&params, "?");
1418 /* Extract arguments from the request and store them in variables. */
1419 if (params) {
1420 char *var, *val;
1421
1422 while ((val = strsep(&params, "&"))) {
1423 var = strsep(&val, "=");
1424 if (val) {
1426 } else {
1427 val = "";
1428 }
1430 if ((v = ast_variable_new(var, val, ""))) {
1431 if (get_vars) {
1432 prev->next = v;
1433 } else {
1434 get_vars = v;
1435 }
1436 prev = v;
1437 }
1438 }
1439 }
1440
1443 if (!strcasecmp(uri, redirect->target)) {
1444 struct ast_str *http_header = ast_str_create(128);
1445
1446 if (!http_header) {
1448 ast_http_error(ser, 500, "Server Error", "Out of memory");
1449 break;
1450 }
1451 ast_str_set(&http_header, 0, "Location: %s\r\n", redirect->dest);
1452 ast_http_send(ser, method, 302, "Moved Temporarily", http_header, NULL, 0, 0);
1453 break;
1454 }
1455 }
1457 if (redirect) {
1458 goto cleanup;
1459 }
1460
1461 /* We want requests to start with the (optional) prefix and '/' */
1462 l = strlen(prefix);
1463 if (!strncasecmp(uri, prefix, l) && uri[l] == '/') {
1464 uri += l + 1;
1465 /* scan registered uris to see if we match one. */
1467 AST_RWLIST_TRAVERSE(&uris, urih, entry) {
1468 l = strlen(urih->uri);
1469 c = uri + l; /* candidate */
1470 ast_debug(2, "match request [%s] with handler [%s] len %d\n", uri, urih->uri, l);
1471 if (strncasecmp(urih->uri, uri, l) /* no match */
1472 || (*c && *c != '/')) { /* substring */
1473 continue;
1474 }
1475 if (*c == '/') {
1476 c++;
1477 }
1478 if (!*c || urih->has_subtree) {
1479 uri = c;
1480 break;
1481 }
1482 }
1484 }
1485 if (urih) {
1486 ast_debug(1, "Match made with [%s]\n", urih->uri);
1487 if (!urih->no_decode_uri) {
1489 }
1490 res = urih->callback(ser, urih, uri, method, get_vars, headers);
1491 } else {
1492 ast_debug(1, "Requested URI [%s] has no handler\n", uri);
1493 ast_http_error(ser, 404, "Not Found", "The requested URL was not found on this server.");
1494 }
1495
1496cleanup:
1497 ast_variables_destroy(get_vars);
1498 return res;
1499}
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:651
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:840
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
unsigned int no_decode_uri
Definition: http.h:114
ast_http_callback callback
Definition: http.h:107

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, method, ast_http_uri::no_decode_uri, NULL, prefix, strsep(), http_uri_redirect::target, ast_http_uri::uri, and var.

Referenced by httpd_process_request().

◆ http_body_check_chunk_sync()

static int http_body_check_chunk_sync ( struct ast_tcptls_session_instance ser)
static

Definition at line 1071 of file http.c.

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

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

◆ http_body_discard_chunk_trailer_headers()

static int http_body_discard_chunk_trailer_headers ( struct ast_tcptls_session_instance ser)
static

Definition at line 1102 of file http.c.

1103{
1104 char header_line[MAX_HTTP_LINE_LENGTH];
1105
1106 for (;;) {
1107 if (ast_iostream_gets(ser->stream, header_line, sizeof(header_line)) <= 0) {
1108 ast_log(LOG_WARNING, "Short HTTP read of chunked trailer header\n");
1109 return -1;
1110 }
1111
1112 /* Trim trailing whitespace */
1113 ast_trim_blanks(header_line);
1114 if (ast_strlen_zero(header_line)) {
1115 /* A blank line ends the chunked-body */
1116 break;
1117 }
1118 }
1119 return 0;
1120}
#define MAX_HTTP_LINE_LENGTH
Definition: http.c:99
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

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

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

967{
968 ssize_t res;
969
970 res = ast_iostream_discard(ser->stream, length);
971 if (res < length) {
972 ast_log(LOG_WARNING, "Short HTTP request %s (Wanted %d but got %zd)\n",
973 what_getting, length, res);
974 return -1;
975 }
976 return 0;
977}
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

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

Referenced by ast_http_body_discard().

◆ http_body_get_chunk_length()

static int http_body_get_chunk_length ( struct ast_tcptls_session_instance ser)
static

Definition at line 1043 of file http.c.

1044{
1045 int length;
1046 char header_line[MAX_HTTP_LINE_LENGTH];
1047
1048 /* get the line of hexadecimal giving chunk-size w/ optional chunk-extension */
1049 if (ast_iostream_gets(ser->stream, header_line, sizeof(header_line)) <= 0) {
1050 ast_log(LOG_WARNING, "Short HTTP read of chunked header\n");
1051 return -1;
1052 }
1053 length = chunked_atoh(header_line, strlen(header_line));
1054 if (length < 0) {
1055 ast_log(LOG_WARNING, "Invalid HTTP chunk size\n");
1056 return -1;
1057 }
1058 return length;
1059}
static int chunked_atoh(const char *s, int len)
Definition: http.c:989

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

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

931{
932 int res;
933 int total = 0;
934
935 /* Stream is in exclusive mode so we get it all if possible. */
936 while (total != length) {
937 res = ast_iostream_read(ser->stream, buf + total, length - total);
938 if (res <= 0) {
939 break;
940 }
941
942 total += res;
943 }
944
945 if (total != length) {
946 ast_log(LOG_WARNING, "Wrong HTTP content read. Request %s (Wanted %d, Read %d)\n",
947 what_getting, length, res);
948 return -1;
949 }
950
951 return 0;
952}
static int total
Definition: res_adsi.c:970

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

Referenced by ast_http_get_contents().

◆ http_check_connection_close()

static int http_check_connection_close ( struct ast_variable headers)
static

Definition at line 829 of file http.c.

830{
831 const char *connection = get_header(headers, "Connection");
832 int close_connection = 0;
833
834 if (connection && !strcasecmp(connection, "close")) {
835 close_connection = -1;
836 }
837 return close_connection;
838}

References get_header().

Referenced by http_request_tracking_setup().

◆ http_request_headers_get()

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

Definition at line 1760 of file http.c.

1761{
1762 struct ast_variable *tail = *headers;
1763 int remaining_headers;
1764 char header_line[MAX_HTTP_LINE_LENGTH];
1765
1766 remaining_headers = MAX_HTTP_REQUEST_HEADERS;
1767 for (;;) {
1768 ssize_t len;
1769 char *name;
1770 char *value;
1771
1772 len = ast_iostream_gets(ser->stream, header_line, sizeof(header_line));
1773 if (len <= 0) {
1774 ast_http_error(ser, 400, "Bad Request", "Timeout");
1775 return -1;
1776 }
1777 if (header_line[len - 1] != '\n') {
1778 /* We didn't get a full line */
1779 ast_http_error(ser, 400, "Bad Request",
1780 (len == sizeof(header_line) - 1) ? "Header line too long" : "Timeout");
1781 return -1;
1782 }
1783
1784 /* Trim trailing characters */
1785 ast_trim_blanks(header_line);
1786 if (ast_strlen_zero(header_line)) {
1787 /* A blank line ends the request header section. */
1788 break;
1789 }
1790
1791 value = header_line;
1792 name = strsep(&value, ":");
1793 if (!value) {
1794 continue;
1795 }
1796
1799 continue;
1800 }
1801
1803
1804 if (!remaining_headers--) {
1805 /* Too many headers. */
1806 ast_http_error(ser, 413, "Request Entity Too Large", "Too many headers");
1807 return -1;
1808 }
1809 if (!*headers) {
1810 *headers = ast_variable_new(name, value, __FILE__);
1811 tail = *headers;
1812 } else {
1813 tail->next = ast_variable_new(name, value, __FILE__);
1814 tail = tail->next;
1815 }
1816 if (!tail) {
1817 /*
1818 * Variable allocation failure.
1819 * Try to make some room.
1820 */
1821 ast_variables_destroy(*headers);
1822 *headers = NULL;
1823
1824 ast_http_error(ser, 500, "Server Error", "Out of memory");
1825 return -1;
1826 }
1827 }
1828
1829 return 0;
1830}
#define MAX_HTTP_REQUEST_HEADERS
Definition: http.c:1747

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, name, ast_variable::next, NULL, ast_tcptls_session_instance::stream, strsep(), and value.

Referenced by httpd_process_request().

◆ http_request_tracking_init()

static void http_request_tracking_init ( struct http_worker_private_data request)
static

Definition at line 854 of file http.c.

855{
858 /* Assume close in case request fails early */
860}
#define ast_set_flags_to(p, flag, value)
Definition: utils.h:104

References ast_set_flags_to, HTTP_FLAG_BODY_READ, HTTP_FLAG_CLOSE_ON_COMPLETION, HTTP_FLAG_HAS_BODY, and request().

Referenced by httpd_helper_thread(), and httpd_process_request().

◆ http_request_tracking_setup()

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

Definition at line 873 of file http.c.

874{
876 const char *transfer_encoding;
877
881
882 transfer_encoding = get_transfer_encoding(headers);
883 if (transfer_encoding && !strcasecmp(transfer_encoding, "chunked")) {
884 request->body_length = -1;
886 return 0;
887 }
888
889 request->body_length = get_content_length(headers);
890 if (0 < request->body_length) {
892 } else if (request->body_length < 0) {
893 /* Invalid Content-Length */
895 ast_http_error(ser, 400, "Bad Request", "Invalid Content-Length in request!");
896 return -1;
897 }
898 return 0;
899}
static int http_check_connection_close(struct ast_variable *headers)
Definition: http.c:829
static const char * get_transfer_encoding(struct ast_variable *headers)
Returns the value of the Transfer-Encoding header.
Definition: http.c:815
static int get_content_length(struct ast_variable *headers)
Returns the value of the Content-Length header.
Definition: http.c:790

References ast_http_error(), ast_set_flag, ast_set_flags_to, 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().

◆ http_server_create()

static struct ast_http_server * http_server_create ( const char *  name,
const char *  address,
const struct ast_sockaddr addr 
)
static

Definition at line 2100 of file http.c.

2102{
2103 struct ast_http_server *server;
2104
2105 server = ao2_alloc(sizeof(*server), http_server_destroy);
2106 if (!server) {
2107 ast_log(LOG_ERROR, "Unable to allocate HTTP server '%s' at address '%s'\n",
2108 name, address);
2109 return NULL;
2110 }
2111
2112 if (!(server->address = ast_strdup(address)) || !(server->name = ast_strdup(name))) {
2113 ast_log(LOG_ERROR, "Unable to complete setup for HTTP server '%s' at address '%s'\n",
2114 name, address);
2115 ao2_ref(server, -1);
2116 return NULL;
2117 }
2118
2119 server->args.accept_fd = -1;
2120 server->args.master = AST_PTHREADT_NULL;
2121 server->args.tls_cfg = NULL;
2122 server->args.poll_timeout = -1;
2123 server->args.name = server->name;
2126
2127 ast_sockaddr_copy(&server->args.local_address, addr);
2128
2129 return server;
2130}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
char * address
Definition: f2c.h:59
static void * httpd_helper_thread(void *arg)
Definition: http.c:1940
static void http_server_destroy(void *obj)
Definition: http.c:2088
#define AST_PTHREADT_NULL
Definition: lock.h:66
char * name
Definition: http.c:122
char * address
Definition: http.c:123
void *(* accept_fn)(void *)
Definition: tcptls.h:140
const char * name
Definition: tcptls.h:143
void *(* worker_fn)(void *)
Definition: tcptls.h:142
void * ast_tcptls_server_root(void *)
Definition: tcptls.c:280

References ast_tcptls_session_args::accept_fd, ast_tcptls_session_args::accept_fn, ast_http_server::address, ao2_alloc, ao2_ref, ast_http_server::args, ast_log, AST_PTHREADT_NULL, ast_sockaddr_copy(), ast_strdup, ast_tcptls_server_root(), http_server_destroy(), httpd_helper_thread(), ast_tcptls_session_args::local_address, LOG_ERROR, ast_tcptls_session_args::master, name, ast_tcptls_session_args::name, ast_http_server::name, NULL, ast_tcptls_session_args::poll_timeout, ast_tcptls_session_args::tls_cfg, and ast_tcptls_session_args::worker_fn.

Referenced by http_server_get_by_addr().

◆ http_server_destroy()

static void http_server_destroy ( void *  obj)
static

Definition at line 2088 of file http.c.

2089{
2090 struct ast_http_server *server = obj;
2091
2092 ast_tcptls_server_stop(&server->args);
2093
2094 ast_verb(1, "Stopped http server '%s' listening at '%s'\n", server->name, server->address);
2095
2096 ast_free(server->name);
2097 ast_free(server->address);
2098}
#define ast_verb(level,...)

References ast_http_server::address, ast_http_server::args, ast_free, ast_tcptls_server_stop(), ast_verb, and ast_http_server::name.

Referenced by http_server_create().

◆ http_server_discard()

static void http_server_discard ( struct ast_http_server server)
static

Discard/Drop a HTTP server.

Decrements the reference to the given object, and unlinks it from the servers container if it's the last reference.

After a server object has been added to the container this method should always be called to decrement the object's reference instead of the regular ao2 methods.

Note
NULL tolerant
Parameters
serverThe server object

Definition at line 2170 of file http.c.

2171{
2172 if (!server) {
2173 return;
2174 }
2175
2176 /*
2177 * If only two references were on the object then the last one is from
2178 * the servers container, so remove from container now.
2179 */
2180 if (ao2_ref(server, -1) == 2) {
2181 ao2_unlink(http_servers, server);
2182 }
2183}
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
struct ao2_container * http_servers
Definition: http.c:2083

References ao2_ref, ao2_unlink, and http_servers.

Referenced by __ast_http_load(), and http_server_get().

◆ http_server_get()

static struct ast_http_server * http_server_get ( const char *  name,
const char *  host,
uint32_t  port,
struct ast_http_server **  replace_me 
)
static

Retrieve, or create and start a HTTP server.

Resolve the given host, and retrieve a listening server object. If the server is not already listening then start it. If a replace_me parameter is given, and it points to a non-NULL value then that server is discarded and replaced.

Parameters
nameThe name of the server
hostThe host to resolve, and match on or create a new object with
portOptional port used if one is not specified with the host (default 8088)
[out]replace_meOptional server to be replaced
Note
If replace_me is specified the returned value is always the same as what's passed back out in the variable.
Returns
a HTTP server object, or NULL on error

Definition at line 2280 of file http.c.

2282{
2283 struct ast_http_server *server;
2284
2286
2287 server = http_server_get_by_host(name, host, port);
2288
2289 if (replace_me) {
2290 /* Only replace if different */
2291 if (*replace_me == server) {
2292 ao2_cleanup(server);
2294 return *replace_me;
2295 }
2296
2297 if (*replace_me) {
2298 http_server_discard(*replace_me);
2299 }
2300
2301 *replace_me = server;
2302 }
2303
2304 if (server && http_server_start(server)) {
2305 if (replace_me) {
2306 *replace_me = NULL;
2307 }
2308
2309 ao2_ref(server, -1);
2310 server = NULL;
2311 }
2312
2314 return server;
2315}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
static int http_server_start(struct ast_http_server *server)
Definition: http.c:2132
static struct ast_http_server * http_server_get_by_host(const char *name, const char *host, uint32_t port)
Retrieve, or create a HTTP server object by host.
Definition: http.c:2228

References ao2_cleanup, ao2_lock, ao2_ref, ao2_unlock, http_server_discard(), http_server_get_by_host(), http_server_start(), http_servers, name, and NULL.

Referenced by __ast_http_load().

◆ http_server_get_by_addr()

static struct ast_http_server * http_server_get_by_addr ( const char *  name,
const struct ast_sockaddr addr 
)
static

Retrieve, or create a HTTP server object by sock address.

Look for, and return a matching server object by addr. If an object is not found then create a new one.

Note
This method should be called with the http_servers container already locked.
Parameters
nameThe name of the server
addrThe address to match on, or create a new object with
Returns
a HTTP server object, or NULL on error

Definition at line 2198 of file http.c.

2200{
2201 struct ast_http_server *server;
2202 const char *address;
2203
2205 if (ast_strlen_zero(address)) {
2206 return NULL;
2207 }
2208
2210
2211 return server ?: http_server_create(name, address, addr);
2212}
#define OBJ_KEY
Definition: astobj2.h:1151
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
static struct ast_http_server * http_server_create(const char *name, const char *address, const struct ast_sockaddr *addr)
Definition: http.c:2100

References ao2_find, ast_sockaddr_stringify(), ast_strlen_zero(), http_server_create(), http_servers, name, NULL, OBJ_KEY, and OBJ_NOLOCK.

Referenced by http_server_get_by_host().

◆ http_server_get_by_host()

static struct ast_http_server * http_server_get_by_host ( const char *  name,
const char *  host,
uint32_t  port 
)
static

Retrieve, or create a HTTP server object by host.

Resolve the given host, and then look for, and return a matching server object. If an object is not found then create a new one.

Note
This method should be called with the http_servers container already locked.
Parameters
nameThe name of the server
hostThe host to resolve, and match on or create a new object with
portOptional port used if one is not specified with the host (default 8088)
Returns
a HTTP server object, or NULL on error

Definition at line 2228 of file http.c.

2230{
2231 struct ast_sockaddr *addrs = NULL;
2232 int num_addrs;
2233 int i;
2234
2235 if (!(num_addrs = ast_sockaddr_resolve(&addrs, host, 0, AST_AF_UNSPEC))) {
2236 ast_log(LOG_WARNING, "Unable to resolve host '%s'\n", host);
2237 return NULL;
2238 }
2239
2240 if (port == 0) {
2241 port = DEFAULT_PORT;
2242 }
2243
2244 for (i = 0; i < num_addrs; ++i) {
2245 struct ast_http_server *server;
2246
2247 /* Use the given port if one was not specified already */
2248 if (!ast_sockaddr_port(&addrs[i])) {
2249 ast_sockaddr_set_port(&addrs[i], port);
2250 }
2251
2252 server = http_server_get_by_addr(name, &addrs[i]);
2253 if (server) {
2254 ast_free(addrs);
2255 return server;
2256 }
2257 }
2258
2259 ast_free(addrs);
2260 return NULL;
2261}
static struct ast_http_server * http_server_get_by_addr(const char *name, const struct ast_sockaddr *addr)
Retrieve, or create a HTTP server object by sock address.
Definition: http.c:2198
@ AST_AF_UNSPEC
Definition: netsock2.h:54
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
Socket address structure.
Definition: netsock2.h:97

References AST_AF_UNSPEC, ast_free, ast_log, ast_sockaddr_port, ast_sockaddr_resolve(), ast_sockaddr_set_port, DEFAULT_PORT, http_server_get_by_addr(), LOG_WARNING, name, and NULL.

Referenced by http_server_get().

◆ http_server_start()

static int http_server_start ( struct ast_http_server server)
static

Definition at line 2132 of file http.c.

2133{
2134 if (server->args.accept_fd != -1) {
2135 /* Already running */
2136 return 0;
2137 }
2138
2139 ast_tcptls_server_start(&server->args);
2140 if (server->args.accept_fd == -1) {
2141 ast_log(LOG_WARNING, "Failed to start HTTP server '%s' at address '%s'\n",
2142 server->name, server->address);
2143 return -1;
2144 }
2145
2146 if (!ao2_link_flags(http_servers, server, OBJ_NOLOCK)) {
2147 ast_log(LOG_WARNING, "Failed to link HTTP server '%s' at address '%s'\n",
2148 server->name, server->address);
2149 return -1;
2150 }
2151
2152 ast_verb(1, "Bound HTTP server '%s' to address %s\n", server->name, server->address);
2153
2154 return 0;
2155}
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554

References ast_tcptls_session_args::accept_fd, ast_http_server::address, ao2_link_flags, ast_http_server::args, ast_log, ast_tcptls_server_start(), ast_verb, http_servers, LOG_WARNING, ast_http_server::name, and OBJ_NOLOCK.

Referenced by http_server_get().

◆ httpd_helper_thread()

static void * httpd_helper_thread ( void *  arg)
static

Definition at line 1940 of file http.c.

1941{
1942 struct ast_tcptls_session_instance *ser = data;
1943 int timeout;
1944 int arg = 1;
1945
1946 if (!ser) {
1947 ao2_cleanup(ser);
1948 return NULL;
1949 }
1950
1952 ast_log(LOG_WARNING, "HTTP session count exceeded %d sessions.\n",
1954 goto done;
1955 }
1956 ast_debug(1, "HTTP opening session. Top level\n");
1957
1958 /*
1959 * Here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
1960 * This is necessary to prevent delays (caused by buffering) as we
1961 * write to the socket in bits and pieces.
1962 */
1963 if (setsockopt(ast_iostream_get_fd(ser->stream), IPPROTO_TCP, TCP_NODELAY, (char *) &arg, sizeof(arg)) < 0) {
1964 ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection: %s\n", strerror(errno));
1965 }
1967
1968 /* Setup HTTP worker private data to keep track of request body reading. */
1972 if (!ser->private_data) {
1973 ast_http_error(ser, 500, "Server Error", "Out of memory");
1974 goto done;
1975 }
1977
1978 /* Determine initial HTTP request wait timeout. */
1979 timeout = session_keep_alive;
1980 if (timeout <= 0) {
1981 /* Persistent connections not enabled. */
1982 timeout = session_inactivity;
1983 }
1984 if (timeout < MIN_INITIAL_REQUEST_TIMEOUT) {
1986 }
1987
1988 /* We can let the stream wait for data to arrive. */
1990
1991 for (;;) {
1992 /* Wait for next potential HTTP request message. */
1994 if (httpd_process_request(ser)) {
1995 /* Break the connection or the connection closed */
1996 break;
1997 }
1998 if (!ser->stream) {
1999 /* Web-socket or similar that took the connection */
2000 break;
2001 }
2002
2003 timeout = session_keep_alive;
2004 if (timeout <= 0) {
2005 /* Persistent connections not enabled. */
2006 break;
2007 }
2008 }
2009
2010done:
2012
2013 ast_debug(1, "HTTP closing session. Top level\n");
2015
2016 ao2_ref(ser, -1);
2017 return NULL;
2018}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define MIN_INITIAL_REQUEST_TIMEOUT
Definition: http.c:75
static void http_request_tracking_init(struct http_worker_private_data *request)
Definition: http.c:854
static int session_count
Definition: http.c:109
static int httpd_process_request(struct ast_tcptls_session_instance *ser)
Definition: http.c:1842
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_iostream_get_fd(struct ast_iostream *stream)
Get an iostream's file descriptor.
Definition: iostream.c:84
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
void ast_iostream_nonblock(struct ast_iostream *stream)
Make an iostream non-blocking.
Definition: iostream.c:103
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:757
describes a server instance
Definition: tcptls.h:150
int done
Definition: test_amihooks.c:48

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, and ast_tcptls_session_instance::stream.

Referenced by http_server_create().

◆ httpd_process_request()

static int httpd_process_request ( struct ast_tcptls_session_instance ser)
static

Definition at line 1842 of file http.c.

1843{
1844 RAII_VAR(struct ast_variable *, headers, NULL, ast_variables_destroy);
1845 char *uri;
1846 char *method;
1847 const char *transfer_encoding;
1849 enum ast_http_method http_method = AST_HTTP_UNKNOWN;
1850 int res;
1851 ssize_t len;
1852 char request_line[MAX_HTTP_LINE_LENGTH];
1853
1854 len = ast_iostream_gets(ser->stream, request_line, sizeof(request_line));
1855 if (len <= 0) {
1856 return -1;
1857 }
1858
1859 /* Re-initialize the request body tracking data. */
1860 request = ser->private_data;
1862
1863 if (request_line[len - 1] != '\n') {
1864 /* We didn't get a full line */
1865 ast_http_error(ser, 400, "Bad Request",
1866 (len == sizeof(request_line) - 1) ? "Request line too long" : "Timeout");
1867 return -1;
1868 }
1869
1870 /* Get method */
1871 method = ast_skip_blanks(request_line);
1873 if (*uri) {
1874 *uri++ = '\0';
1875 }
1876
1877 if (!strcasecmp(method,"GET")) {
1878 http_method = AST_HTTP_GET;
1879 } else if (!strcasecmp(method,"POST")) {
1880 http_method = AST_HTTP_POST;
1881 } else if (!strcasecmp(method,"HEAD")) {
1882 http_method = AST_HTTP_HEAD;
1883 } else if (!strcasecmp(method,"PUT")) {
1884 http_method = AST_HTTP_PUT;
1885 } else if (!strcasecmp(method,"DELETE")) {
1886 http_method = AST_HTTP_DELETE;
1887 } else if (!strcasecmp(method,"OPTIONS")) {
1888 http_method = AST_HTTP_OPTIONS;
1889 }
1890
1891 uri = ast_skip_blanks(uri); /* Skip white space */
1892 if (*uri) { /* terminate at the first blank */
1893 char *c = ast_skip_nonblanks(uri);
1894
1895 if (*c) {
1896 *c = '\0';
1897 }
1898 } else {
1899 ast_http_error(ser, 400, "Bad Request", "Invalid Request");
1900 return -1;
1901 }
1902
1903 if (ast_shutdown_final()) {
1904 ast_http_error(ser, 503, "Service Unavailable", "Shutdown in progress");
1905 return -1;
1906 }
1907
1908 /* process "Request Headers" lines */
1909 if (http_request_headers_get(ser, &headers)) {
1910 return -1;
1911 }
1912
1913 transfer_encoding = get_transfer_encoding(headers);
1914 /* Transfer encoding defaults to identity */
1915 if (!transfer_encoding) {
1916 transfer_encoding = "identity";
1917 }
1918
1919 /*
1920 * RFC 2616, section 3.6, we should respond with a 501 for any transfer-
1921 * codings we don't understand.
1922 */
1923 if (strcasecmp(transfer_encoding, "identity") != 0 &&
1924 strcasecmp(transfer_encoding, "chunked") != 0) {
1925 /* Transfer encodings not supported */
1926 ast_http_error(ser, 501, "Unimplemented", "Unsupported Transfer-Encoding.");
1927 return -1;
1928 }
1929
1930 if (http_request_tracking_setup(ser, headers)
1931 || handle_uri(ser, uri, http_method, headers)
1933 res = -1;
1934 } else {
1935 res = 0;
1936 }
1937 return res;
1938}
int ast_shutdown_final(void)
Definition: asterisk.c:1867
static int http_request_headers_get(struct ast_tcptls_session_instance *ser, struct ast_variable **headers)
Definition: http.c:1760
static int http_request_tracking_setup(struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
Definition: http.c:873
static int handle_uri(struct ast_tcptls_session_instance *ser, char *uri, enum ast_http_method method, struct ast_variable *headers)
Definition: http.c:1404
ast_http_method
HTTP Request methods known by Asterisk.
Definition: http.h:58
@ AST_HTTP_PUT
Definition: http.h:63
@ AST_HTTP_DELETE
Definition: http.h:64
@ AST_HTTP_POST
Definition: http.h:61
@ AST_HTTP_GET
Definition: http.h:60
@ AST_HTTP_OPTIONS
Definition: http.h:65
char * ast_skip_nonblanks(const char *str)
Gets a pointer to first whitespace character in a string.
Definition: strings.h:204

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

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

375{
376 struct ast_str *out;
377 struct ast_variable *v, *cookies = NULL;
378
380 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
381 return 0;
382 }
383
384 out = ast_str_create(512);
385 if (!out) {
387 ast_http_error(ser, 500, "Server Error", "Out of memory");
388 return 0;
389 }
390
392 "<html><title>Asterisk HTTP Status</title>\r\n"
393 "<body bgcolor=\"#ffffff\">\r\n"
394 "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n"
395 "<h2>&nbsp;&nbsp;Asterisk&trade; HTTP Status</h2></td></tr>\r\n");
396
397 ast_str_append(&out, 0, "<tr><td><i>Server</i></td><td><b>%s</b></td></tr>\r\n", http_server_name);
398 ast_str_append(&out, 0, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix);
399 if (global_http_server) {
400 ast_str_append(&out, 0, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
402 }
403 if (http_tls_cfg.enabled) {
404 ast_str_append(&out, 0, "<tr><td><i>TLS Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
406 }
407 ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
408 for (v = get_vars; v; v = v->next) {
409 ast_str_append(&out, 0, "<tr><td><i>Submitted GET Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
410 }
411 ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
412
413 cookies = ast_http_get_cookies(headers);
414 for (v = cookies; v; v = v->next) {
415 ast_str_append(&out, 0, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
416 }
417 ast_variables_destroy(cookies);
418
419 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");
420 ast_http_send(ser, method, 200, NULL, NULL, out, 0, 0);
421 return 0;
422}
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:1139

References ast_http_server::args, 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(), ast_str_append(), ast_str_create, ast_variables_destroy(), ast_tls_config::enabled, global_http_server, http_server_name, http_tls_cfg, https_desc, method, ast_variable::name, ast_variable::next, NULL, ast_tcptls_session_args::old_address, out, prefix, and ast_variable::value.

◆ load_module()

static int load_module ( void  )
static

Definition at line 2656 of file http.c.

2657{
2659
2661 HTTP_SERVER_BUCKETS, ast_http_server_hash_fn, NULL, ast_http_server_cmp_fn);
2662 if (!http_servers) {
2664 }
2665
2666 if (__ast_http_load(0)) {
2670 }
2671
2673}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static int __ast_http_load(int reload)
Definition: http.c:2367
static struct ast_cli_entry cli_http[]
Definition: http.c:2619
#define HTTP_SERVER_BUCKETS
Number of HTTP server buckets.
Definition: http.c:2081
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition: module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70

References __ast_http_load(), AO2_ALLOC_OPT_LOCK_MUTEX, ao2_cleanup, ao2_container_alloc_hash, ARRAY_LEN, ast_cli_register_multiple, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, cli_http, HTTP_SERVER_BUCKETS, http_servers, and NULL.

◆ parse_cookies()

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

Definition at line 1501 of file http.c.

1502{
1503 char *parse = ast_strdupa(cookies);
1504 char *cur;
1505 struct ast_variable *vars = NULL, *var;
1506
1507 while ((cur = strsep(&parse, ";"))) {
1508 char *name, *val;
1509
1510 name = val = cur;
1511 strsep(&val, "=");
1512
1514 continue;
1515 }
1516
1517 name = ast_strip(name);
1518 val = ast_strip_quoted(val, "\"", "\"");
1519
1521 continue;
1522 }
1523
1524 ast_debug(1, "HTTP Cookie, Name: '%s' Value: '%s'\n", name, val);
1525
1526 var = ast_variable_new(name, val, __FILE__);
1527 var->next = vars;
1528 vars = var;
1529 }
1530
1531 return vars;
1532}
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: utils.c:1818
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223

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

Referenced by ast_http_get_cookies().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 2614 of file http.c.

2615{
2616 return __ast_http_load(1);
2617}

References __ast_http_load().

◆ remove_excess_lws()

static void remove_excess_lws ( char *  s)
static

Definition at line 1662 of file http.c.

1663{
1664 char *p, *res = s;
1665 char *buf = ast_malloc(strlen(s) + 1);
1666 char *buf_end;
1667
1668 if (!buf) {
1669 return;
1670 }
1671
1672 buf_end = buf;
1673
1674 while (*s && *(s = ast_skip_blanks(s))) {
1675 p = s;
1676 s = ast_skip_nonblanks(s);
1677
1678 if (buf_end != buf) {
1679 *buf_end++ = ' ';
1680 }
1681
1682 memcpy(buf_end, p, s - p);
1683 buf_end += s - p;
1684 }
1685 *buf_end = '\0';
1686 /* safe since buf will always be less than or equal to res */
1687 strcpy(res, buf);
1688 ast_free(buf);
1689}

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

Referenced by ast_http_header_parse().

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

247{
248 char *path;
249 const char *ftype;
250 const char *mtype;
251 char wkspace[80];
252 struct stat st;
253 int len;
254 int fd;
255 struct ast_str *http_header;
256 struct timeval tv;
257 struct ast_tm tm;
258 char timebuf[80], etag[23];
259 struct ast_variable *v;
260 int not_modified = 0;
261
263 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
264 return 0;
265 }
266
267 /* Yuck. I'm not really sold on this, but if you don't deliver static content it
268 * makes your configuration substantially more challenging, but this seems like a
269 * rather irritating feature creep on Asterisk.
270 *
271 * XXX: It is not clear to me what this comment means or if it is any longer
272 * relevant. */
273 if (ast_strlen_zero(uri)) {
274 goto out403;
275 }
276
277 /* Disallow any funny filenames at all (checking first character only??) */
278 if ((uri[0] < 33) || strchr("./|~@#$%^&*() \t", uri[0])) {
279 goto out403;
280 }
281
282 if (strstr(uri, "/..")) {
283 goto out403;
284 }
285
286 if ((ftype = strrchr(uri, '.'))) {
287 ftype++;
288 }
289
290 if (!(mtype = ast_http_ftype2mtype(ftype))) {
291 snprintf(wkspace, sizeof(wkspace), "text/%s", S_OR(ftype, "plain"));
292 mtype = wkspace;
293 }
294
295 /* Cap maximum length */
296 if ((len = strlen(uri) + strlen(ast_config_AST_DATA_DIR) + strlen("/static-http/") + 5) > 1024) {
297 goto out403;
298 }
299
300 path = ast_alloca(len);
301 sprintf(path, "%s/static-http/%s", ast_config_AST_DATA_DIR, uri);
302 if (stat(path, &st)) {
303 goto out404;
304 }
305
306 if (S_ISDIR(st.st_mode)) {
307 goto out404;
308 }
309
310 if (strstr(path, "/private/") && !astman_is_authed(ast_http_manid_from_vars(headers))) {
311 goto out403;
312 }
313
314 fd = open(path, O_RDONLY);
315 if (fd < 0) {
316 goto out403;
317 }
318
319 /* make "Etag:" http header value */
320 snprintf(etag, sizeof(etag), "\"%ld\"", (long)st.st_mtime);
321
322 /* make "Last-Modified:" http header value */
323 tv.tv_sec = st.st_mtime;
324 tv.tv_usec = 0;
325 ast_strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", ast_localtime(&tv, &tm, "GMT"));
326
327 /* check received "If-None-Match" request header and Etag value for file */
328 for (v = headers; v; v = v->next) {
329 if (!strcasecmp(v->name, "If-None-Match")) {
330 if (!strcasecmp(v->value, etag)) {
331 not_modified = 1;
332 }
333 break;
334 }
335 }
336
337 http_header = ast_str_create(255);
338 if (!http_header) {
340 ast_http_error(ser, 500, "Server Error", "Out of memory");
341 close(fd);
342 return 0;
343 }
344
345 ast_str_set(&http_header, 0, "Content-type: %s\r\n"
346 "ETag: %s\r\n"
347 "Last-Modified: %s\r\n",
348 mtype,
349 etag,
350 timebuf);
351
352 /* ast_http_send() frees http_header, so we don't need to do it before returning */
353 if (not_modified) {
354 ast_http_send(ser, method, 304, "Not Modified", http_header, NULL, 0, 1);
355 } else {
356 ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 1); /* static content flag is set */
357 }
358 close(fd);
359 return 0;
360
361out404:
362 ast_http_error(ser, 404, "Not Found", "The requested URL was not found on this server.");
363 return 0;
364
365out403:
367 ast_http_error(ser, 403, "Access Denied", "You do not have permission to access the requested URL.");
368 return 0;
369}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
const char * mtype
Definition: http.c:151
const char * ast_http_ftype2mtype(const char *ftype)
Return mime type based on extension.
Definition: http.c:206
uint32_t ast_http_manid_from_vars(struct ast_variable *headers)
Return manager id, if exist, from request headers.
Definition: http.c:220
int astman_is_authed(uint32_t ident)
Determine if a manager session ident is authenticated.
Definition: manager.c:8333
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80

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(), method, mtype, ast_variable::name, ast_variable::next, NULL, S_OR, and ast_variable::value.

◆ unload_module()

static int unload_module ( void  )
static

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 = AST_BUILDOPT_SUM, .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 2682 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 2682 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:2559

Definition at line 2619 of file http.c.

Referenced by load_module(), and unload_module().

◆ ext

const char* ext

◆ global_http_server

struct ast_http_server* global_http_server = NULL

The default configured HTTP server

Definition at line 129 of file http.c.

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

◆ http_server_name

char http_server_name[MAX_SERVER_NAME_LENGTH]
static

◆ http_servers

struct ao2_container* http_servers = NULL

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

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

◆ 

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

Referenced by is_msg(), and static_callback().

◆ prefix

char prefix[MAX_PREFIX]
static

Definition at line 144 of file http.c.

Referenced by __ast_http_load(), _while_exec(), aoc_amount_str(), aoc_d_event(), aoc_e_event(), aoc_s_event(), aoc_time_str(), aor_deleted_observer(), ast_acl_output(), ast_ari_get_docs(), ast_begins_with(), ast_cli_print_timestr_fromseconds(), ast_db_deltree(), ast_db_gettree(), ast_db_gettree_by_prefix(), ast_frame_dump(), ast_ha_output(), ast_http_prefix(), ast_http_uri_link(), ast_manager_build_bridge_state_string_prefix(), ast_manager_build_channel_state_string_prefix(), ast_remotecontrol(), ast_sip_location_retrieve_aor_contacts_nolock_filtered(), ast_sorcery_retrieve_by_prefix(), at_match_prefix(), clearvar_prefix(), cli_match_char_tree(), console_print(), exec_clearhash(), generate_filenames_string(), get_index(), get_key(), get_object_variables(), handle_auth(), handle_cli_database_show(), handle_show_http(), handle_uri(), hashkeys_read(), hashkeys_read2(), httpstatus_callback(), if_helper(), insert_test_duplicates(), insert_test_vector(), ip_identify_match_srv_lookup(), load_module(), log_jack_status(), manager_db_tree_get(), print_acl(), print_uptimestr(), process_config(), refer_blind_callback(), say_date_generic(), shared_read(), shared_write(), sip_options_apply_aor_configuration(), sorcery_astdb_create(), sorcery_astdb_delete(), sorcery_astdb_retrieve_fields_common(), sorcery_astdb_retrieve_id(), sorcery_astdb_retrieve_prefix(), sorcery_astdb_retrieve_regex(), sorcery_astdb_update(), sorcery_config_retrieve_prefix(), sorcery_memory_cache_retrieve_prefix(), sorcery_memory_retrieve_prefix(), sorcery_realtime_retrieve_prefix(), test_ao2_callback_traversal(), test_ao2_iteration(), test_expected_duplicates(), vm_authenticate(), and while_continue_exec().

◆ 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

◆ static_uri

struct ast_http_uri static_uri
static

Definition at line 433 of file http.c.

Referenced by __ast_http_load(), and unload_module().

◆ static_uri_enabled

int static_uri_enabled
static

Definition at line 145 of file http.c.

Referenced by __ast_http_load(), and unload_module().

◆ status_uri

struct ast_http_uri status_uri
static

Definition at line 424 of file http.c.

Referenced by __ast_http_load(), and unload_module().

◆ status_uri_enabled

int status_uri_enabled
static

Definition at line 146 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