Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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...
 
enum ast_http_method ast_get_http_method_from_string (const char *method)
 Return http method from 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...
 
struct ast_variableast_http_create_basic_auth_header (const char *userid, const char *password)
 Create an HTTP authorization header. 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...
 
struct ast_variableast_http_parse_post_form (char *buf, int content_length, const char *content_type)
 Get post variables from an application/x-www-form-urlencoded buffer. 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 1609 of file http.c.

◆ BASIC_PREFIX

#define BASIC_PREFIX   "Basic "

Definition at line 1608 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 2154 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 1820 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 455 of file http.c.

455 {
456 /*! TRUE if the HTTP request has a body. */
457 HTTP_FLAG_HAS_BODY = (1 << 0),
458 /*! TRUE if the HTTP request body has been read. */
459 HTTP_FLAG_BODY_READ = (1 << 1),
460 /*! TRUE if the HTTP request must close when completed. */
462};
@ HTTP_FLAG_BODY_READ
Definition: http.c:459
@ HTTP_FLAG_CLOSE_ON_COMPLETION
Definition: http.c:461
@ HTTP_FLAG_HAS_BODY
Definition: http.c:457

Function Documentation

◆ __ast_http_load()

static int __ast_http_load ( int  reload)
static

Definition at line 2440 of file http.c.

2441{
2442 struct ast_config *cfg;
2443 struct ast_variable *v;
2444 int enabled = 0;
2445 int new_static_uri_enabled = 0;
2446 int new_status_uri_enabled = 1; /* Default to enabled for BC */
2447 char newprefix[MAX_PREFIX] = "";
2448 char server_name[MAX_SERVER_NAME_LENGTH];
2449 struct http_uri_redirect *redirect;
2450 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2451 uint32_t bindport = DEFAULT_PORT;
2452 int http_tls_was_enabled = 0;
2453 char *bindaddr = NULL;
2454
2455 cfg = ast_config_load2("http.conf", "http", config_flags);
2456 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
2457 return 0;
2458 }
2459
2460 /* Even if the http.conf hasn't been updated, the TLS certs/keys may have been */
2461 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2464 }
2465 return 0;
2466 }
2467
2468 http_tls_was_enabled = (reload && http_tls_cfg.enabled);
2469
2471
2474
2477
2480
2481 /* Apply modern intermediate settings according to the Mozilla OpSec team as of July 30th, 2015 but disable TLSv1 */
2483
2485 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");
2486
2488 while ((redirect = AST_RWLIST_REMOVE_HEAD(&uri_redirects, entry))) {
2489 ast_free(redirect);
2490 }
2492
2494
2498
2499 snprintf(server_name, sizeof(server_name), "Asterisk/%s", ast_get_version());
2500
2501 v = ast_variable_browse(cfg, "general");
2502 for (; v; v = v->next) {
2503 /* read tls config options while preventing unsupported options from being set */
2504 if (strcasecmp(v->name, "tlscafile")
2505 && strcasecmp(v->name, "tlscapath")
2506 && strcasecmp(v->name, "tlscadir")
2507 && strcasecmp(v->name, "tlsverifyclient")
2508 && strcasecmp(v->name, "tlsdontverifyserver")
2509 && strcasecmp(v->name, "tlsclientmethod")
2510 && strcasecmp(v->name, "sslclientmethod")
2512 continue;
2513 }
2514
2515 if (!strcasecmp(v->name, "servername")) {
2516 if (!ast_strlen_zero(v->value)) {
2517 ast_copy_string(server_name, v->value, sizeof(server_name));
2518 } else {
2519 server_name[0] = '\0';
2520 }
2521 } else if (!strcasecmp(v->name, "enabled")) {
2522 enabled = ast_true(v->value);
2523 } else if (!strcasecmp(v->name, "enablestatic") || !strcasecmp(v->name, "enable_static")) {
2524 new_static_uri_enabled = ast_true(v->value);
2525 } else if (!strcasecmp(v->name, "enable_status")) {
2526 new_status_uri_enabled = ast_true(v->value);
2527 } else if (!strcasecmp(v->name, "bindport")) {
2529 &bindport, DEFAULT_PORT, 0, 65535)) {
2530 ast_log(LOG_WARNING, "Invalid port %s specified. Using default port %" PRId32 "\n",
2531 v->value, DEFAULT_PORT);
2532 }
2533 } else if (!strcasecmp(v->name, "bindaddr")) {
2535 } else if (!strcasecmp(v->name, "prefix")) {
2536 if (!ast_strlen_zero(v->value)) {
2537 newprefix[0] = '/';
2538 ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
2539 } else {
2540 newprefix[0] = '\0';
2541 }
2542 } else if (!strcasecmp(v->name, "redirect")) {
2543 add_redirect(v->value);
2544 } else if (!strcasecmp(v->name, "sessionlimit")) {
2546 &session_limit, DEFAULT_SESSION_LIMIT, 1, INT_MAX)) {
2547 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2548 v->name, v->value, v->lineno);
2549 }
2550 } else if (!strcasecmp(v->name, "session_inactivity")) {
2553 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2554 v->name, v->value, v->lineno);
2555 }
2556 } else if (!strcasecmp(v->name, "session_keep_alive")) {
2557 if (sscanf(v->value, "%30d", &session_keep_alive) != 1
2558 || session_keep_alive < 0) {
2560 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2561 v->name, v->value, v->lineno);
2562 }
2563 } else {
2564 ast_log(LOG_WARNING, "Ignoring unknown option '%s' in http.conf\n", v->name);
2565 }
2566 }
2567
2568 ast_config_destroy(cfg);
2569
2570 if (strcmp(prefix, newprefix)) {
2571 ast_copy_string(prefix, newprefix, sizeof(prefix));
2572 }
2573
2574 ast_copy_string(http_server_name, server_name, sizeof(http_server_name));
2575
2576 if (enabled) {
2577 http_server_get("http server", bindaddr, bindport, &global_http_server);
2578 } else if (global_http_server) {
2581 }
2582
2583 /* When no specific TLS bindaddr is specified, we just use
2584 * the non-TLS bindaddress here.
2585 */
2588
2590 /* Of course, we can't use the same port though.
2591 * Since no bind address was specified, we just use the
2592 * default TLS port
2593 */
2595 }
2596
2597 if (http_tls_was_enabled && !http_tls_cfg.enabled) {
2600 /* We can get here either because a TLS-specific address was specified
2601 * or because we copied the non-TLS address here. In the case where
2602 * we read an explicit address from the config, there may have been
2603 * no port specified, so we'll just use the default TLS port.
2604 */
2607 }
2610 }
2611 }
2612
2613 if (static_uri_enabled && !new_static_uri_enabled) {
2615 } else if (!static_uri_enabled && new_static_uri_enabled) {
2617 }
2618
2619 static_uri_enabled = new_static_uri_enabled;
2620
2621 if (status_uri_enabled && !new_status_uri_enabled) {
2623 } else if (!status_uri_enabled && new_status_uri_enabled) {
2625 }
2626
2627 status_uri_enabled = new_status_uri_enabled;
2628
2629 return 0;
2630}
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:2098
int ast_http_uri_link(struct ast_http_uri *urih)
Link the new uri into the list.
Definition: http.c:689
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:437
static void http_server_discard(struct ast_http_server *server)
Discard/Drop a HTTP server.
Definition: http.c:2243
#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:721
static struct ast_http_uri static_uri
Definition: http.c:446
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:2353
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:3541
@ CONFIG_FLAG_FILEUNCHANGED
#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:4047
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
#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
#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:933
int ast_ssl_setup(struct ast_tls_config *cfg)
Set up an SSL server.
Definition: tcptls.c:577
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:768
@ 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:959
#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 2755 of file http.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

2099{
2100 char *target, *dest;
2101 struct http_uri_redirect *redirect, *cur;
2102 unsigned int target_len;
2103 unsigned int total_len;
2104 size_t dest_len;
2105
2108 target = strsep(&dest, " ");
2110 target = strsep(&target, " "); /* trim trailing whitespace */
2111
2112 if (!dest) {
2113 ast_log(LOG_WARNING, "Invalid redirect '%s'\n", value);
2114 return;
2115 }
2116
2117 target_len = strlen(target) + 1;
2118 dest_len = strlen(dest) + 1;
2119 total_len = sizeof(*redirect) + target_len + dest_len;
2120
2121 if (!(redirect = ast_calloc(1, total_len))) {
2122 return;
2123 }
2124 redirect->dest = redirect->target + target_len;
2125 strcpy(redirect->target, target);
2126 ast_copy_string(redirect->dest, dest, dest_len);
2127
2129
2130 target_len--; /* So we can compare directly with strlen() */
2132 || strlen(AST_RWLIST_FIRST(&uri_redirects)->target) <= target_len ) {
2135
2136 return;
2137 }
2138
2140 if (AST_RWLIST_NEXT(cur, entry)
2141 && strlen(AST_RWLIST_NEXT(cur, entry)->target) <= target_len ) {
2144 return;
2145 }
2146 }
2147
2149
2151}
char * strsep(char **str, const char *delims)
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#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
struct http_uri_redirect::@363 entry
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, http_uri_redirect::entry, 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_get_http_method_from_string()

enum ast_http_method ast_get_http_method_from_string ( const char *  method)

Return http method from string.

Definition at line 206 of file http.c.

207{
208 int x;
209
210 for (x = 0; x < ARRAY_LEN(ast_http_methods_text); x++) {
213 }
214 }
215
216 return AST_HTTP_UNKNOWN;
217}
char * text
Definition: app_queue.c:1809
@ AST_HTTP_UNKNOWN
Definition: http.h:59
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition: strings.c:238
enum ast_http_method method
Definition: http.c:181

References ARRAY_LEN, ast_http_methods_text, AST_HTTP_UNKNOWN, ast_strings_equal(), ast_cfhttp_methods_text::method, method, and text.

Referenced by parse_rest_request_msg().

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

641{
642 int status_code = 401;
643 char *status_title = "Unauthorized";
644 struct ast_str *http_header_data = ast_str_create(DEFAULT_RESPONSE_HEADER_LENGTH);
645
646 if (http_header_data) {
647 ast_str_set(&http_header_data,
648 0,
649 "WWW-authenticate: Digest algorithm=MD5, realm=\"%s\", nonce=\"%08lx\", qop=\"auth\", opaque=\"%08lx\"%s\r\n"
650 "Content-type: text/html\r\n",
651 realm ? realm : "Asterisk",
652 nonce,
653 opaque,
654 stale ? ", stale=true" : "");
655 }
656
658 status_code,
659 status_title,
660 http_header_data,
661 text);
662}
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:583
#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 1135 of file http.c.

1136{
1138
1139 request = ser->private_data;
1142 /* No body to read or it has already been read. */
1143 return 0;
1144 }
1146
1147 ast_debug(1, "HTTP discarding unused request body\n");
1148
1149 ast_assert(request->body_length != 0);
1150 if (0 < request->body_length) {
1151 if (http_body_discard_contents(ser, request->body_length, "body")) {
1153 return -1;
1154 }
1155 return 0;
1156 }
1157
1158 /* parse chunked-body */
1159 for (;;) {
1160 int length;
1161
1162 length = http_body_get_chunk_length(ser);
1163 if (length < 0) {
1165 return -1;
1166 }
1167 if (length == 0) {
1168 /* parsed last-chunk */
1169 break;
1170 }
1171
1172 if (http_body_discard_contents(ser, length, "chunk-data")
1175 return -1;
1176 }
1177 }
1178
1179 /* Read and discard any trailer entity-header lines. */
1182 return -1;
1183 }
1184 return 0;
1185}
static int request(void *obj)
Definition: chan_pjsip.c:2605
static int http_body_discard_chunk_trailer_headers(struct ast_tcptls_session_instance *ser)
Definition: http.c:1115
static int http_body_discard_contents(struct ast_tcptls_session_instance *ser, int length, const char *what_getting)
Definition: http.c:979
static int http_body_check_chunk_sync(struct ast_tcptls_session_instance *ser)
Definition: http.c:1084
static int http_body_get_chunk_length(struct ast_tcptls_session_instance *ser)
Definition: http.c:1056
#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 914 of file http.c.

915{
917
918 request = ser->private_data;
921 /* No body to read. */
922 return;
923 }
925 if (!read_success) {
927 }
928}

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

struct ast_variable * ast_http_create_basic_auth_header ( const char *  userid,
const char *  password 
)

Create an HTTP authorization header.

The returned ast_variable must be freed with ast_variables_destroy()

Parameters
useridUser ID or "<userid>:<password>".
passwordPassword if not in userid.
Returns
ast_variable with name="Authorization" and value="Basic <base64enc>"
Return values
NULLif memory allocation failed.

Definition at line 1668 of file http.c.

1670{
1671 int encoded_size = 0;
1672 int userinfo_len = 0;
1673 RAII_VAR(char *, userinfo, NULL, ast_free);
1674 char *encoded_userinfo = NULL;
1675 struct ast_variable *auth_header = NULL;
1676
1677 if (ast_strlen_zero(userid)) {
1678 return NULL;
1679 }
1680
1681 if (strchr(userid, ':')) {
1682 userinfo = ast_strdup(userid);
1683 userinfo_len = strlen(userinfo);
1684 } else {
1685 if (ast_strlen_zero(password)) {
1686 return NULL;
1687 }
1688 userinfo_len = ast_asprintf(&userinfo, "%s:%s", userid, password);
1689 }
1690 if (!userinfo) {
1691 return NULL;
1692 }
1693
1694 /*
1695 * The header value is "Basic " + base64(userinfo).
1696 * Doubling the userinfo length then adding the length
1697 * of the "Basic " prefix is a conservative estimate of the
1698 * final encoded size.
1699 */
1700 encoded_size = userinfo_len * 2 * sizeof(char) + 1 + BASIC_LEN;
1701 encoded_userinfo = ast_alloca(encoded_size);
1702 strcpy(encoded_userinfo, BASIC_PREFIX); /* Safe */
1703 ast_base64encode(encoded_userinfo + BASIC_LEN, (unsigned char *)userinfo,
1704 userinfo_len, encoded_size - BASIC_LEN);
1705
1706 auth_header = ast_variable_new("Authorization",
1707 encoded_userinfo, "");
1708
1709 return auth_header;
1710}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define BASIC_PREFIX
Definition: http.c:1608
#define BASIC_LEN
Definition: http.c:1609
#define ast_variable_new(name, value, filename)
#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
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: utils.c:406

References ast_alloca, ast_asprintf, ast_base64encode(), ast_free, ast_strdup, ast_strlen_zero(), ast_variable_new, BASIC_LEN, BASIC_PREFIX, NULL, and RAII_VAR.

Referenced by websocket_client_handshake().

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

585{
586 char server_name[MAX_SERVER_NAME_LENGTH];
587 struct ast_str *server_address = ast_str_create(MAX_SERVER_NAME_LENGTH);
589
590 if (!http_header_data || !server_address || !out) {
591 ast_free(http_header_data);
592 ast_free(server_address);
593 ast_free(out);
594 if (ser) {
595 ast_debug(1, "HTTP closing session. OOM.\n");
597 }
598 return;
599 }
600
602 ast_xml_escape(http_server_name, server_name, sizeof(server_name));
603 ast_str_set(&server_address,
604 0,
605 "<address>%s</address>\r\n",
606 server_name);
607 }
608
610 0,
611 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
612 "<html><head>\r\n"
613 "<title>%d %s</title>\r\n"
614 "</head><body>\r\n"
615 "<h1>%s</h1>\r\n"
616 "<p>%s</p>\r\n"
617 "<hr />\r\n"
618 "%s"
619 "</body></html>\r\n",
620 status_code,
621 status_title,
622 status_title,
623 text ? text : "",
624 ast_str_buffer(server_address));
625
626 ast_free(server_address);
627
628 ast_http_send(ser,
630 status_code,
631 status_title,
632 http_header_data,
633 out,
634 0,
635 0);
636}
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:472
#define INITIAL_RESPONSE_BODY_BUFFER
Definition: http.c:92
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:923
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 
)

Send HTTP error message and close socket.

Definition at line 664 of file http.c.

666{
667 struct ast_str *http_header_data = ast_str_create(DEFAULT_RESPONSE_HEADER_LENGTH);
668
669 if (http_header_data) {
670 ast_str_set(&http_header_data, 0, "Content-type: text/html\r\n");
671 }
672
674 status_code,
675 status_title,
676 http_header_data,
677 text);
678}

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

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

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

220{
221 int x;
222
223 if (ftype) {
224 for (x = 0; x < ARRAY_LEN(mimetypes); x++) {
225 if (!strcasecmp(ftype, mimetypes[x].ext)) {
226 return mimetypes[x].mtype;
227 }
228 }
229 }
230 return NULL;
231}
static struct @362 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 1611 of file http.c.

1612{
1613 struct ast_variable *v;
1614
1615 for (v = headers; v; v = v->next) {
1616 const char *base64;
1617 char decoded[256] = {};
1618 char *username;
1619 char *password;
1620#ifdef AST_DEVMODE
1621 int cnt;
1622#endif /* AST_DEVMODE */
1623
1624 if (strcasecmp("Authorization", v->name) != 0) {
1625 continue;
1626 }
1627
1630 "Unsupported Authorization scheme\n");
1631 continue;
1632 }
1633
1634 /* Basic auth header parsing. RFC 2617, section 2.
1635 * credentials = "Basic" basic-credentials
1636 * basic-credentials = base64-user-pass
1637 * base64-user-pass = <base64 encoding of user-pass,
1638 * except not limited to 76 char/line>
1639 * user-pass = userid ":" password
1640 */
1641
1642 base64 = v->value + BASIC_LEN;
1643
1644 /* This will truncate "userid:password" lines to
1645 * sizeof(decoded). The array is long enough that this shouldn't
1646 * be a problem */
1647#ifdef AST_DEVMODE
1648 cnt =
1649#endif /* AST_DEVMODE */
1650 ast_base64decode((unsigned char*)decoded, base64,
1651 sizeof(decoded) - 1);
1652 ast_assert(cnt < sizeof(decoded));
1653
1654 /* Split the string at the colon */
1655 password = decoded;
1656 username = strsep(&password, ":");
1657 if (!password) {
1658 ast_log(LOG_WARNING, "Invalid Authorization header\n");
1659 return NULL;
1660 }
1661
1662 return auth_create(username, password);
1663 }
1664
1665 return NULL;
1666}
static struct ast_http_auth * auth_create(const char *userid, const char *password)
Definition: http.c:1577
#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 1197 of file http.c.

1199{
1201 int content_length;
1202 int bufsize;
1203 char *buf;
1204
1205 request = ser->private_data;
1206 if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)) {
1207 /* no content - not an error */
1208 return NULL;
1209 }
1211 /* Already read the body. Cannot read again. Assume no content. */
1212 ast_assert(0);
1213 return NULL;
1214 }
1216
1217 ast_debug(2, "HTTP consuming request body\n");
1218
1219 ast_assert(request->body_length != 0);
1220 if (0 < request->body_length) {
1221 /* handle regular non-chunked content */
1222 content_length = request->body_length;
1223 if (content_length > MAX_CONTENT_LENGTH) {
1224 ast_log(LOG_WARNING, "Excessively long HTTP content. (%d > %d)\n",
1225 content_length, MAX_CONTENT_LENGTH);
1227 errno = EFBIG;
1228 return NULL;
1229 }
1230 buf = ast_malloc(content_length + 1);
1231 if (!buf) {
1232 /* Malloc sets ENOMEM */
1234 return NULL;
1235 }
1236
1237 if (http_body_read_contents(ser, buf, content_length, "body")) {
1239 errno = EIO;
1240 ast_free(buf);
1241 return NULL;
1242 }
1243
1244 buf[content_length] = 0;
1245 *return_length = content_length;
1246 return buf;
1247 }
1248
1249 /* pre-allocate buffer */
1250 bufsize = 250;
1251 buf = ast_malloc(bufsize);
1252 if (!buf) {
1254 return NULL;
1255 }
1256
1257 /* parse chunked-body */
1258 content_length = 0;
1259 for (;;) {
1260 int chunk_length;
1261
1262 chunk_length = http_body_get_chunk_length(ser);
1263 if (chunk_length < 0) {
1265 errno = EIO;
1266 ast_free(buf);
1267 return NULL;
1268 }
1269 if (chunk_length == 0) {
1270 /* parsed last-chunk */
1271 break;
1272 }
1273 if (content_length + chunk_length > MAX_CONTENT_LENGTH) {
1275 "Excessively long HTTP accumulated chunked body. (%d + %d > %d)\n",
1276 content_length, chunk_length, MAX_CONTENT_LENGTH);
1278 errno = EFBIG;
1279 ast_free(buf);
1280 return NULL;
1281 }
1282
1283 /* insure buffer is large enough +1 */
1284 if (content_length + chunk_length >= bufsize) {
1285 char *new_buf;
1286
1287 /* Increase bufsize until it can handle the expected data. */
1288 do {
1289 bufsize *= 2;
1290 } while (content_length + chunk_length >= bufsize);
1291
1292 new_buf = ast_realloc(buf, bufsize);
1293 if (!new_buf) {
1295 ast_free(buf);
1296 return NULL;
1297 }
1298 buf = new_buf;
1299 }
1300
1301 if (http_body_read_contents(ser, buf + content_length, chunk_length, "chunk-data")
1304 errno = EIO;
1305 ast_free(buf);
1306 return NULL;
1307 }
1308 content_length += chunk_length;
1309 }
1310
1311 /*
1312 * Read and discard any trailer entity-header lines
1313 * which we don't care about.
1314 *
1315 * XXX In the future we may need to add the trailer headers
1316 * to the passed in headers list rather than discarding them.
1317 */
1320 errno = EIO;
1321 ast_free(buf);
1322 return NULL;
1323 }
1324
1325 buf[content_length] = 0;
1326 *return_length = content_length;
1327 return buf;
1328}
#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:943
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 1564 of file http.c.

1565{
1566 struct ast_variable *v, *cookies = NULL;
1567
1568 for (v = headers; v; v = v->next) {
1569 if (!strcasecmp(v->name, "Cookie")) {
1570 ast_variables_destroy(cookies);
1571 cookies = parse_cookies(v->value);
1572 }
1573 }
1574 return cookies;
1575}
static struct ast_variable * parse_cookies(const char *cookies)
Definition: http.c:1530
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 1330 of file http.c.

1332{
1333 int content_length = 0;
1334 struct ast_json *body;
1335 RAII_VAR(char *, buf, NULL, ast_free);
1336 RAII_VAR(char *, type, get_content_type(headers), ast_free);
1337
1338 /* Use errno to distinguish errors from no body */
1339 errno = 0;
1340
1341 if (ast_strlen_zero(type) || strcasecmp(type, "application/json")) {
1342 /* Content type is not JSON. Don't read the body. */
1343 return NULL;
1344 }
1345
1346 buf = ast_http_get_contents(&content_length, ser, headers);
1347 if (!buf || !content_length) {
1348 /*
1349 * errno already set
1350 * or it is not an error to have zero content
1351 */
1352 return NULL;
1353 }
1354
1355 body = ast_json_load_buf(buf, content_length, NULL);
1356 if (!body) {
1357 /* Failed to parse JSON; treat as an I/O error */
1358 errno = EIO;
1359 return NULL;
1360 }
1361
1362 return body;
1363}
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:778
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:1197
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, ...).

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

1407{
1408 int content_length = 0;
1409 RAII_VAR(char *, buf, NULL, ast_free);
1410 RAII_VAR(char *, type, get_content_type(headers), ast_free);
1411
1412 /* Use errno to distinguish errors from no params */
1413 errno = 0;
1414
1415 if (ast_strlen_zero(type) ||
1416 strcasecmp(type, "application/x-www-form-urlencoded")) {
1417 /* Content type is not form data. Don't read the body. */
1418 return NULL;
1419 }
1420
1421 buf = ast_http_get_contents(&content_length, ser, headers);
1422 if (!buf || !content_length) {
1423 /*
1424 * errno already set
1425 * or it is not an error to have zero content
1426 */
1427 return NULL;
1428 }
1429
1430 return ast_http_parse_post_form(buf, content_length, type);
1431}
struct ast_variable * ast_http_parse_post_form(char *buf, int content_length, const char *content_type)
Get post variables from an application/x-www-form-urlencoded buffer.
Definition: http.c:1369

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

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

1788{
1789 if (strcasecmp(name, expected_name)) {
1790 /* no value to validate if names don't match */
1791 return 0;
1792 }
1793
1794 if (strcasecmp(value, expected_value)) {
1795 ast_log(LOG_ERROR, "Invalid header value - expected %s "
1796 "received %s", value, expected_value);
1797 return -1;
1798 }
1799 return 1;
1800}
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 1802 of file http.c.

1804{
1805 if (strcasecmp(name, expected_name)) {
1806 /* no value to validate if names don't match */
1807 return 0;
1808 }
1809
1810 if (!strcasestr(expected_value, value)) {
1811 ast_log(LOG_ERROR, "Header '%s' - could not locate '%s' "
1812 "in '%s'\n", name, value, expected_value);
1813 return -1;
1814
1815 }
1816 return 1;
1817}
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 1764 of file http.c.

1765{
1767 if (ast_strlen_zero(buf)) {
1768 return -1;
1769 }
1770
1771 *value = buf;
1772 *name = strsep(value, ":");
1773 if (!*value) {
1774 return 1;
1775 }
1776
1779 return 1;
1780 }
1781
1783 return 0;
1784}
static void remove_excess_lws(char *s)
Definition: http.c:1735
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 233 of file http.c.

234{
235 uint32_t mngid = 0;
236 struct ast_variable *v, *cookies;
237
238 cookies = ast_http_get_cookies(headers);
239 for (v = cookies; v; v = v->next) {
240 if (!strcasecmp(v->name, "mansession_id")) {
241 sscanf(v->value, "%30x", &mngid);
242 break;
243 }
244 }
245 ast_variables_destroy(cookies);
246 return mngid;
247}
struct ast_variable * ast_http_get_cookies(struct ast_variable *headers)
Get cookie from Request headers.
Definition: http.c:1564

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

struct ast_variable * ast_http_parse_post_form ( char *  buf,
int  content_length,
const char *  content_type 
)

Get post variables from an application/x-www-form-urlencoded buffer.

Parameters
bufinput buffer
content_lenBuffer length
content_typeContent type (must be "application/x-www-form-urlencoded")
Warning
The input buffer will be modified by strsep() so pass in a copy if you need to keep the original.
Returns
List of ast_variables from the buffer. Must be freed with ast_variables_destroy().

Definition at line 1369 of file http.c.

1371{
1372 struct ast_variable *v, *post_vars=NULL, *prev = NULL;
1373 char *var, *val;
1374
1375 /* Use errno to distinguish errors from no params */
1376 errno = 0;
1377
1378 if (ast_strlen_zero(content_type) ||
1379 strcasecmp(content_type, "application/x-www-form-urlencoded") != 0) {
1380 /* Content type is not form data. Don't read the body. */
1381 return NULL;
1382 }
1383
1384 while ((val = strsep(&buf, "&"))) {
1385 var = strsep(&val, "=");
1386 if (val) {
1388 } else {
1389 val = "";
1390 }
1392 if ((v = ast_variable_new(var, val, ""))) {
1393 if (post_vars) {
1394 prev->next = v;
1395 } else {
1396 post_vars = v;
1397 }
1398 prev = v;
1399 }
1400 }
1401
1402 return post_vars;
1403}
#define var
Definition: ast_expr2f.c:605
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_strlen_zero(), ast_uri_decode(), ast_uri_http_legacy, ast_variable_new, buf, errno, NULL, strsep(), and var.

Referenced by ast_http_get_post_vars(), and parse_rest_request_msg().

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

250{
251 if (buf) {
253 }
254}
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 853 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(), ast_ari_invoke(), 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 1712 of file http.c.

1713{
1714 int status_code;
1715 size_t size = strlen(version);
1716
1717 if (strncmp(buf, version, size) || buf[size] != ' ') {
1718 ast_log(LOG_ERROR, "HTTP version not supported - "
1719 "expected %s\n", version);
1720 return -1;
1721 }
1722
1723 /* skip to status code (version + space) */
1724 buf += size + 1;
1725
1726 if (sscanf(buf, "%d", &status_code) != 1) {
1727 ast_log(LOG_ERROR, "Could not read HTTP status code - "
1728 "%s\n", buf);
1729 return -1;
1730 }
1731
1732 return status_code;
1733}
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 472 of file http.c.

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

690{
691 struct ast_http_uri *uri;
692 int len = strlen(urih->uri);
693
695
696 urih->prefix = prefix;
697
698 if ( AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len ) {
701 return 0;
702 }
703
705 if (AST_RWLIST_NEXT(uri, entry) &&
706 strlen(AST_RWLIST_NEXT(uri, entry)->uri) <= len) {
709
710 return 0;
711 }
712 }
713
715
717
718 return 0;
719}
Definition of a URI handler.
Definition: http.h:102
const char * prefix
Definition: http.h:106
const char * uri
Definition: http.h:105
struct ast_http_uri::@230 entry
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, ast_http_uri::entry, 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 721 of file http.c.

722{
724 AST_RWLIST_REMOVE(&uris, urih, entry);
726}
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:885

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

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

729{
730 struct ast_http_uri *urih;
733 if (!strcmp(urih->key, key)) {
735 if (urih->dmallocd) {
736 ast_free(urih->data);
737 }
738 if (urih->mallocd) {
739 ast_free(urih);
740 }
741 }
742 }
745}
#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::entry, 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 2755 of file http.c.

◆ auth_create()

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

Definition at line 1577 of file http.c.

1578{
1579 struct ast_http_auth *auth;
1580 size_t userid_len;
1581 size_t password_len;
1582
1583 if (!userid || !password) {
1584 ast_log(LOG_ERROR, "Invalid userid/password\n");
1585 return NULL;
1586 }
1587
1588 userid_len = strlen(userid) + 1;
1589 password_len = strlen(password) + 1;
1590
1591 /* Allocate enough room to store everything in one memory block */
1592 auth = ao2_alloc(sizeof(*auth) + userid_len + password_len, NULL);
1593 if (!auth) {
1594 return NULL;
1595 }
1596
1597 /* Put the userid right after the struct */
1598 auth->userid = (char *)(auth + 1);
1599 strcpy(auth->userid, userid);
1600
1601 /* Put the password right after the userid */
1602 auth->password = auth->userid + userid_len;
1603 strcpy(auth->password, password);
1604
1605 return auth;
1606}
#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 1002 of file http.c.

1003{
1004 int value = 0;
1005 char c;
1006
1007 if (*s < '0') {
1008 /* zero value must be 0\n not just \n */
1009 return -1;
1010 }
1011
1012 while (len--) {
1013 c = *s++;
1014 if (c == '\x0D') {
1015 return value;
1016 }
1017 if (c == ';') {
1018 /* We have a chunk-extension that we don't care about. */
1019 while (len--) {
1020 if (*s++ == '\x0D') {
1021 return value;
1022 }
1023 }
1024 break;
1025 }
1026 value <<= 4;
1027 if (c >= '0' && c <= '9') {
1028 value += c - '0';
1029 continue;
1030 }
1031 if (c >= 'a' && c <= 'f') {
1032 value += 10 + c - 'a';
1033 continue;
1034 }
1035 if (c >= 'A' && c <= 'F') {
1036 value += 10 + c - 'A';
1037 continue;
1038 }
1039 /* invalid character */
1040 return -1;
1041 }
1042 /* end of string */
1043 return -1;
1044}
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 803 of file http.c.

804{
805 const char *content_length = get_header(headers, "Content-Length");
806 int length;
807
808 if (!content_length) {
809 /* Missing content length; assume zero */
810 return 0;
811 }
812
813 length = 0;
814 if (sscanf(content_length, "%30d", &length) != 1) {
815 /* Invalid Content-Length value */
816 length = -1;
817 }
818 return length;
819}
static const char * get_header(struct ast_variable *headers, const char *field_name)
Retrieves the header with the given field name.
Definition: http.c:755

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

779{
780 const char *content_type = get_header(headers, "Content-Type");
781 const char *param;
782 size_t size;
783
784 if (!content_type) {
785 return NULL;
786 }
787
788 param = strchr(content_type, ';');
789 size = param ? param - content_type : strlen(content_type);
790
791 return ast_strndup(content_type, size);
792}
#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 755 of file http.c.

756{
757 struct ast_variable *v;
758
759 for (v = headers; v; v = v->next) {
760 if (!strcasecmp(v->name, field_name)) {
761 return v->value;
762 }
763 }
764 return NULL;
765}

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

829{
830 return get_header(headers, "Transfer-Encoding");
831}

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

2633{
2634 struct ast_http_uri *urih;
2635 struct http_uri_redirect *redirect;
2636
2637 switch (cmd) {
2638 case CLI_INIT:
2639 e->command = "http show status";
2640 e->usage =
2641 "Usage: http show status\n"
2642 " Lists status of internal HTTP engine\n";
2643 return NULL;
2644 case CLI_GENERATE:
2645 return NULL;
2646 }
2647
2648 if (a->argc != 3) {
2649 return CLI_SHOWUSAGE;
2650 }
2651 ast_cli(a->fd, "HTTP Server Status:\n");
2652 ast_cli(a->fd, "Prefix: %s\n", prefix);
2653 ast_cli(a->fd, "Server: %s\n", http_server_name);
2654 if (!global_http_server) {
2655 ast_cli(a->fd, "Server Disabled\n\n");
2656 } else {
2657 ast_cli(a->fd, "Server Enabled and Bound to %s\n\n",
2659 if (http_tls_cfg.enabled) {
2660 ast_cli(a->fd, "HTTPS Server Enabled and Bound to %s\n\n",
2662 }
2663 }
2664
2665 ast_cli(a->fd, "Enabled URI's:\n");
2667 if (AST_RWLIST_EMPTY(&uris)) {
2668 ast_cli(a->fd, "None.\n");
2669 } else {
2671 ast_cli(a->fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
2672 }
2674
2675 ast_cli(a->fd, "\nEnabled Redirects:\n");
2678 ast_cli(a->fd, " %s => %s\n", redirect->target, redirect->dest);
2680 ast_cli(a->fd, " None.\n");
2681 }
2683
2684 return CLI_SUCCESS;
2685}
#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, http_uri_redirect::entry, 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 1433 of file http.c.

1435{
1436 char *c;
1437 int res = 0;
1438 char *params = uri;
1439 struct ast_http_uri *urih = NULL;
1440 int l;
1441 struct ast_variable *get_vars = NULL, *v, *prev = NULL;
1442 struct http_uri_redirect *redirect;
1443
1444 ast_debug(2, "HTTP Request URI is %s \n", uri);
1445
1446 strsep(&params, "?");
1447 /* Extract arguments from the request and store them in variables. */
1448 if (params) {
1449 char *var, *val;
1450
1451 while ((val = strsep(&params, "&"))) {
1452 var = strsep(&val, "=");
1453 if (val) {
1455 } else {
1456 val = "";
1457 }
1459 if ((v = ast_variable_new(var, val, ""))) {
1460 if (get_vars) {
1461 prev->next = v;
1462 } else {
1463 get_vars = v;
1464 }
1465 prev = v;
1466 }
1467 }
1468 }
1469
1472 if (!strcasecmp(uri, redirect->target)) {
1473 struct ast_str *http_header = ast_str_create(128);
1474
1475 if (!http_header) {
1477 ast_http_error(ser, 500, "Server Error", "Out of memory");
1478 break;
1479 }
1480 ast_str_set(&http_header, 0, "Location: %s\r\n", redirect->dest);
1481 ast_http_send(ser, method, 302, "Moved Temporarily", http_header, NULL, 0, 0);
1482 break;
1483 }
1484 }
1486 if (redirect) {
1487 goto cleanup;
1488 }
1489
1490 /* We want requests to start with the (optional) prefix and '/' */
1491 l = strlen(prefix);
1492 if (!strncasecmp(uri, prefix, l) && uri[l] == '/') {
1493 uri += l + 1;
1494 /* scan registered uris to see if we match one. */
1496 AST_RWLIST_TRAVERSE(&uris, urih, entry) {
1497 l = strlen(urih->uri);
1498 c = uri + l; /* candidate */
1499 ast_debug(2, "match request [%s] with handler [%s] len %d\n", uri, urih->uri, l);
1500 if (strncasecmp(urih->uri, uri, l) /* no match */
1501 || (*c && *c != '/')) { /* substring */
1502 continue;
1503 }
1504 if (*c == '/') {
1505 c++;
1506 }
1507 if (!*c || urih->has_subtree) {
1508 uri = c;
1509 break;
1510 }
1511 }
1513 }
1514 if (urih) {
1515 ast_debug(1, "Match made with [%s]\n", urih->uri);
1516 if (!urih->no_decode_uri) {
1518 }
1519 res = urih->callback(ser, urih, uri, method, get_vars, headers);
1520 } else {
1521 ast_debug(1, "Requested URI [%s] has no handler\n", uri);
1522 ast_http_error(ser, 404, "Not Found", "The requested URL was not found on this server.");
1523 }
1524
1525cleanup:
1526 ast_variables_destroy(get_vars);
1527 return res;
1528}
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:664
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:853
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, http_uri_redirect::entry, 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 1084 of file http.c.

1085{
1086 int res;
1087 char chunk_sync[2];
1088
1089 /* Stay in fread until get the expected CRLF or timeout. */
1090 res = ast_iostream_read(ser->stream, chunk_sync, sizeof(chunk_sync));
1091 if (res < sizeof(chunk_sync)) {
1092 ast_log(LOG_WARNING, "Short HTTP chunk sync read (Wanted %zu)\n",
1093 sizeof(chunk_sync));
1094 return -1;
1095 }
1096 if (chunk_sync[0] != 0x0D || chunk_sync[1] != 0x0A) {
1097 ast_log(LOG_WARNING, "HTTP chunk sync bytes wrong (0x%02hhX, 0x%02hhX)\n",
1098 (unsigned char) chunk_sync[0], (unsigned char) chunk_sync[1]);
1099 return -1;
1100 }
1101
1102 return 0;
1103}
ssize_t ast_iostream_read(struct ast_iostream *stream, void *buffer, size_t count)
Read data from an iostream.
Definition: iostream.c:284

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

1116{
1117 char header_line[MAX_HTTP_LINE_LENGTH];
1118
1119 for (;;) {
1120 if (ast_iostream_gets(ser->stream, header_line, sizeof(header_line)) <= 0) {
1121 ast_log(LOG_WARNING, "Short HTTP read of chunked trailer header\n");
1122 return -1;
1123 }
1124
1125 /* Trim trailing whitespace */
1126 ast_trim_blanks(header_line);
1127 if (ast_strlen_zero(header_line)) {
1128 /* A blank line ends the chunked-body */
1129 break;
1130 }
1131 }
1132 return 0;
1133}
#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:311

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

980{
981 ssize_t res;
982
983 res = ast_iostream_discard(ser->stream, length);
984 if (res < length) {
985 ast_log(LOG_WARNING, "Short HTTP request %s (Wanted %d but got %zd)\n",
986 what_getting, length, res);
987 return -1;
988 }
989 return 0;
990}
ssize_t ast_iostream_discard(struct ast_iostream *stream, size_t count)
Discard the specified number of bytes from an iostream.
Definition: iostream.c:368

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

1057{
1058 int length;
1059 char header_line[MAX_HTTP_LINE_LENGTH];
1060
1061 /* get the line of hexadecimal giving chunk-size w/ optional chunk-extension */
1062 if (ast_iostream_gets(ser->stream, header_line, sizeof(header_line)) <= 0) {
1063 ast_log(LOG_WARNING, "Short HTTP read of chunked header\n");
1064 return -1;
1065 }
1066 length = chunked_atoh(header_line, strlen(header_line));
1067 if (length < 0) {
1068 ast_log(LOG_WARNING, "Invalid HTTP chunk size\n");
1069 return -1;
1070 }
1071 return length;
1072}
static int chunked_atoh(const char *s, int len)
Definition: http.c:1002

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

944{
945 int res;
946 int total = 0;
947
948 /* Stream is in exclusive mode so we get it all if possible. */
949 while (total != length) {
950 res = ast_iostream_read(ser->stream, buf + total, length - total);
951 if (res <= 0) {
952 break;
953 }
954
955 total += res;
956 }
957
958 if (total != length) {
959 ast_log(LOG_WARNING, "Wrong HTTP content read. Request %s (Wanted %d, Read %d)\n",
960 what_getting, length, res);
961 return -1;
962 }
963
964 return 0;
965}
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 842 of file http.c.

843{
844 const char *connection = get_header(headers, "Connection");
845 int close_connection = 0;
846
847 if (connection && !strcasecmp(connection, "close")) {
848 close_connection = -1;
849 }
850 return close_connection;
851}

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

1834{
1835 struct ast_variable *tail = *headers;
1836 int remaining_headers;
1837 char header_line[MAX_HTTP_LINE_LENGTH];
1838
1839 remaining_headers = MAX_HTTP_REQUEST_HEADERS;
1840 for (;;) {
1841 ssize_t len;
1842 char *name;
1843 char *value;
1844
1845 len = ast_iostream_gets(ser->stream, header_line, sizeof(header_line));
1846 if (len <= 0) {
1847 ast_http_error(ser, 400, "Bad Request", "Timeout");
1848 return -1;
1849 }
1850 if (header_line[len - 1] != '\n') {
1851 /* We didn't get a full line */
1852 ast_http_error(ser, 400, "Bad Request",
1853 (len == sizeof(header_line) - 1) ? "Header line too long" : "Timeout");
1854 return -1;
1855 }
1856
1857 /* Trim trailing characters */
1858 ast_trim_blanks(header_line);
1859 if (ast_strlen_zero(header_line)) {
1860 /* A blank line ends the request header section. */
1861 break;
1862 }
1863
1864 value = header_line;
1865 name = strsep(&value, ":");
1866 if (!value) {
1867 continue;
1868 }
1869
1872 continue;
1873 }
1874
1876
1877 if (!remaining_headers--) {
1878 /* Too many headers. */
1879 ast_http_error(ser, 413, "Request Entity Too Large", "Too many headers");
1880 return -1;
1881 }
1882 if (!*headers) {
1883 *headers = ast_variable_new(name, value, __FILE__);
1884 tail = *headers;
1885 } else {
1886 tail->next = ast_variable_new(name, value, __FILE__);
1887 tail = tail->next;
1888 }
1889 if (!tail) {
1890 /*
1891 * Variable allocation failure.
1892 * Try to make some room.
1893 */
1894 ast_variables_destroy(*headers);
1895 *headers = NULL;
1896
1897 ast_http_error(ser, 500, "Server Error", "Out of memory");
1898 return -1;
1899 }
1900 }
1901
1902 return 0;
1903}
#define MAX_HTTP_REQUEST_HEADERS
Definition: http.c:1820

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

868{
871 /* Assume close in case request fails early */
873}
#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 886 of file http.c.

887{
889 const char *transfer_encoding;
890
894
895 transfer_encoding = get_transfer_encoding(headers);
896 if (transfer_encoding && !strcasecmp(transfer_encoding, "chunked")) {
897 request->body_length = -1;
899 return 0;
900 }
901
902 request->body_length = get_content_length(headers);
903 if (0 < request->body_length) {
905 } else if (request->body_length < 0) {
906 /* Invalid Content-Length */
908 ast_http_error(ser, 400, "Bad Request", "Invalid Content-Length in request!");
909 return -1;
910 }
911 return 0;
912}
static int http_check_connection_close(struct ast_variable *headers)
Definition: http.c:842
static const char * get_transfer_encoding(struct ast_variable *headers)
Returns the value of the Transfer-Encoding header.
Definition: http.c:828
static int get_content_length(struct ast_variable *headers)
Returns the value of the Content-Length header.
Definition: http.c:803

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

2175{
2176 struct ast_http_server *server;
2177
2178 server = ao2_alloc(sizeof(*server), http_server_destroy);
2179 if (!server) {
2180 ast_log(LOG_ERROR, "Unable to allocate HTTP server '%s' at address '%s'\n",
2181 name, address);
2182 return NULL;
2183 }
2184
2185 if (!(server->address = ast_strdup(address)) || !(server->name = ast_strdup(name))) {
2186 ast_log(LOG_ERROR, "Unable to complete setup for HTTP server '%s' at address '%s'\n",
2187 name, address);
2188 ao2_ref(server, -1);
2189 return NULL;
2190 }
2191
2192 server->args.accept_fd = -1;
2193 server->args.master = AST_PTHREADT_NULL;
2194 server->args.tls_cfg = NULL;
2195 server->args.poll_timeout = -1;
2196 server->args.name = server->name;
2199
2200 ast_sockaddr_copy(&server->args.local_address, addr);
2201
2202 return server;
2203}
#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:2013
static void http_server_destroy(void *obj)
Definition: http.c:2161
#define AST_PTHREADT_NULL
Definition: lock.h:70
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 2161 of file http.c.

2162{
2163 struct ast_http_server *server = obj;
2164
2165 ast_tcptls_server_stop(&server->args);
2166
2167 ast_verb(1, "Stopped http server '%s' listening at '%s'\n", server->name, server->address);
2168
2169 ast_free(server->name);
2170 ast_free(server->address);
2171}
#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 2243 of file http.c.

2244{
2245 if (!server) {
2246 return;
2247 }
2248
2249 /*
2250 * If only two references were on the object then the last one is from
2251 * the servers container, so remove from container now.
2252 */
2253 if (ao2_ref(server, -1) == 2) {
2254 ao2_unlink(http_servers, server);
2255 }
2256}
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
struct ao2_container * http_servers
Definition: http.c:2156

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

2355{
2356 struct ast_http_server *server;
2357
2359
2360 server = http_server_get_by_host(name, host, port);
2361
2362 if (replace_me) {
2363 /* Only replace if different */
2364 if (*replace_me == server) {
2365 ao2_cleanup(server);
2367 return *replace_me;
2368 }
2369
2370 if (*replace_me) {
2371 http_server_discard(*replace_me);
2372 }
2373
2374 *replace_me = server;
2375 }
2376
2377 if (server && http_server_start(server)) {
2378 if (replace_me) {
2379 *replace_me = NULL;
2380 }
2381
2382 ao2_ref(server, -1);
2383 server = NULL;
2384 }
2385
2387 return server;
2388}
#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:2205
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:2301

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

2273{
2274 struct ast_http_server *server;
2275 const char *address;
2276
2278 if (ast_strlen_zero(address)) {
2279 return NULL;
2280 }
2281
2283
2284 return server ?: http_server_create(name, address, addr);
2285}
#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:2173

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

2303{
2304 struct ast_sockaddr *addrs = NULL;
2305 int num_addrs;
2306 int i;
2307
2308 if (!(num_addrs = ast_sockaddr_resolve(&addrs, host, 0, AST_AF_UNSPEC))) {
2309 ast_log(LOG_WARNING, "Unable to resolve host '%s'\n", host);
2310 return NULL;
2311 }
2312
2313 if (port == 0) {
2314 port = DEFAULT_PORT;
2315 }
2316
2317 for (i = 0; i < num_addrs; ++i) {
2318 struct ast_http_server *server;
2319
2320 /* Use the given port if one was not specified already */
2321 if (!ast_sockaddr_port(&addrs[i])) {
2322 ast_sockaddr_set_port(&addrs[i], port);
2323 }
2324
2325 server = http_server_get_by_addr(name, &addrs[i]);
2326 if (server) {
2327 ast_free(addrs);
2328 return server;
2329 }
2330 }
2331
2332 ast_free(addrs);
2333 return NULL;
2334}
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:2271
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
@ AST_AF_UNSPEC
Definition: netsock2.h:54
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 2205 of file http.c.

2206{
2207 if (server->args.accept_fd != -1) {
2208 /* Already running */
2209 return 0;
2210 }
2211
2212 ast_tcptls_server_start(&server->args);
2213 if (server->args.accept_fd == -1) {
2214 ast_log(LOG_WARNING, "Failed to start HTTP server '%s' at address '%s'\n",
2215 server->name, server->address);
2216 return -1;
2217 }
2218
2219 if (!ao2_link_flags(http_servers, server, OBJ_NOLOCK)) {
2220 ast_log(LOG_WARNING, "Failed to link HTTP server '%s' at address '%s'\n",
2221 server->name, server->address);
2222 return -1;
2223 }
2224
2225 ast_verb(1, "Bound HTTP server '%s' to address %s\n", server->name, server->address);
2226
2227 return 0;
2228}
#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 2013 of file http.c.

2014{
2015 struct ast_tcptls_session_instance *ser = data;
2016 int timeout;
2017 int arg = 1;
2018
2019 if (!ser) {
2020 ao2_cleanup(ser);
2021 return NULL;
2022 }
2023
2025 ast_log(LOG_WARNING, "HTTP session count exceeded %d sessions.\n",
2027 goto done;
2028 }
2029 ast_debug(1, "HTTP opening session. Top level\n");
2030
2031 /*
2032 * Here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
2033 * This is necessary to prevent delays (caused by buffering) as we
2034 * write to the socket in bits and pieces.
2035 */
2036 if (setsockopt(ast_iostream_get_fd(ser->stream), IPPROTO_TCP, TCP_NODELAY, (char *) &arg, sizeof(arg)) < 0) {
2037 ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection: %s\n", strerror(errno));
2038 }
2040
2041 /* Setup HTTP worker private data to keep track of request body reading. */
2045 if (!ser->private_data) {
2046 ast_http_error(ser, 500, "Server Error", "Out of memory");
2047 goto done;
2048 }
2050
2051 /* Determine initial HTTP request wait timeout. */
2052 timeout = session_keep_alive;
2053 if (timeout <= 0) {
2054 /* Persistent connections not enabled. */
2055 timeout = session_inactivity;
2056 }
2057 if (timeout < MIN_INITIAL_REQUEST_TIMEOUT) {
2059 }
2060
2061 /* We can let the stream wait for data to arrive. */
2063
2064 for (;;) {
2065 /* Wait for next potential HTTP request message. */
2067 if (httpd_process_request(ser)) {
2068 /* Break the connection or the connection closed */
2069 break;
2070 }
2071 if (!ser->stream) {
2072 /* Web-socket or similar that took the connection */
2073 break;
2074 }
2075
2076 timeout = session_keep_alive;
2077 if (timeout <= 0) {
2078 /* Persistent connections not enabled. */
2079 break;
2080 }
2081 }
2082
2083done:
2085
2086 ast_debug(1, "HTTP closing session. Top level\n");
2088
2089 ao2_ref(ser, -1);
2090 return NULL;
2091}
@ 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:867
static int session_count
Definition: http.c:109
static int httpd_process_request(struct ast_tcptls_session_instance *ser)
Definition: http.c:1915
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:131
int ast_iostream_get_fd(struct ast_iostream *stream)
Get an iostream's file descriptor.
Definition: iostream.c:85
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:149
void ast_iostream_nonblock(struct ast_iostream *stream)
Make an iostream non-blocking.
Definition: iostream.c:104
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:761
describes a server instance
Definition: tcptls.h:151
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 1915 of file http.c.

1916{
1917 RAII_VAR(struct ast_variable *, headers, NULL, ast_variables_destroy);
1918 char *uri;
1919 char *method;
1920 const char *transfer_encoding;
1922 enum ast_http_method http_method = AST_HTTP_UNKNOWN;
1923 int res;
1924 ssize_t len;
1925 char request_line[MAX_HTTP_LINE_LENGTH];
1926
1927 len = ast_iostream_gets(ser->stream, request_line, sizeof(request_line));
1928 if (len <= 0) {
1929 return -1;
1930 }
1931
1932 /* Re-initialize the request body tracking data. */
1933 request = ser->private_data;
1935
1936 if (request_line[len - 1] != '\n') {
1937 /* We didn't get a full line */
1938 ast_http_error(ser, 400, "Bad Request",
1939 (len == sizeof(request_line) - 1) ? "Request line too long" : "Timeout");
1940 return -1;
1941 }
1942
1943 /* Get method */
1944 method = ast_skip_blanks(request_line);
1946 if (*uri) {
1947 *uri++ = '\0';
1948 }
1949
1950 if (!strcasecmp(method,"GET")) {
1951 http_method = AST_HTTP_GET;
1952 } else if (!strcasecmp(method,"POST")) {
1953 http_method = AST_HTTP_POST;
1954 } else if (!strcasecmp(method,"HEAD")) {
1955 http_method = AST_HTTP_HEAD;
1956 } else if (!strcasecmp(method,"PUT")) {
1957 http_method = AST_HTTP_PUT;
1958 } else if (!strcasecmp(method,"DELETE")) {
1959 http_method = AST_HTTP_DELETE;
1960 } else if (!strcasecmp(method,"OPTIONS")) {
1961 http_method = AST_HTTP_OPTIONS;
1962 }
1963
1964 uri = ast_skip_blanks(uri); /* Skip white space */
1965 if (*uri) { /* terminate at the first blank */
1966 char *c = ast_skip_nonblanks(uri);
1967
1968 if (*c) {
1969 *c = '\0';
1970 }
1971 } else {
1972 ast_http_error(ser, 400, "Bad Request", "Invalid Request");
1973 return -1;
1974 }
1975
1976 if (ast_shutdown_final()) {
1977 ast_http_error(ser, 503, "Service Unavailable", "Shutdown in progress");
1978 return -1;
1979 }
1980
1981 /* process "Request Headers" lines */
1982 if (http_request_headers_get(ser, &headers)) {
1983 return -1;
1984 }
1985
1986 transfer_encoding = get_transfer_encoding(headers);
1987 /* Transfer encoding defaults to identity */
1988 if (!transfer_encoding) {
1989 transfer_encoding = "identity";
1990 }
1991
1992 /*
1993 * RFC 2616, section 3.6, we should respond with a 501 for any transfer-
1994 * codings we don't understand.
1995 */
1996 if (strcasecmp(transfer_encoding, "identity") != 0 &&
1997 strcasecmp(transfer_encoding, "chunked") != 0) {
1998 /* Transfer encodings not supported */
1999 ast_http_error(ser, 501, "Unimplemented", "Unsupported Transfer-Encoding.");
2000 return -1;
2001 }
2002
2003 if (http_request_tracking_setup(ser, headers)
2004 || handle_uri(ser, uri, http_method, headers)
2006 res = -1;
2007 } else {
2008 res = 0;
2009 }
2010 return res;
2011}
int ast_shutdown_final(void)
Definition: asterisk.c:1878
static int http_request_headers_get(struct ast_tcptls_session_instance *ser, struct ast_variable **headers)
Definition: http.c:1833
static int http_request_tracking_setup(struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
Definition: http.c:886
static int handle_uri(struct ast_tcptls_session_instance *ser, char *uri, enum ast_http_method method, struct ast_variable *headers)
Definition: http.c:1433
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 384 of file http.c.

388{
389 struct ast_str *out;
390 struct ast_variable *v, *cookies = NULL;
391
393 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
394 return 0;
395 }
396
397 out = ast_str_create(512);
398 if (!out) {
400 ast_http_error(ser, 500, "Server Error", "Out of memory");
401 return 0;
402 }
403
405 "<html><title>Asterisk HTTP Status</title>\r\n"
406 "<body bgcolor=\"#ffffff\">\r\n"
407 "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n"
408 "<h2>&nbsp;&nbsp;Asterisk&trade; HTTP Status</h2></td></tr>\r\n");
409
410 ast_str_append(&out, 0, "<tr><td><i>Server</i></td><td><b>%s</b></td></tr>\r\n", http_server_name);
411 ast_str_append(&out, 0, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix);
412 if (global_http_server) {
413 ast_str_append(&out, 0, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
415 }
416 if (http_tls_cfg.enabled) {
417 ast_str_append(&out, 0, "<tr><td><i>TLS Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
419 }
420 ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
421 for (v = get_vars; v; v = v->next) {
422 ast_str_append(&out, 0, "<tr><td><i>Submitted GET Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
423 }
424 ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
425
426 cookies = ast_http_get_cookies(headers);
427 for (v = cookies; v; v = v->next) {
428 ast_str_append(&out, 0, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
429 }
430 ast_variables_destroy(cookies);
431
432 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");
433 ast_http_send(ser, method, 200, NULL, NULL, out, 0, 0);
434 return 0;
435}
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 2729 of file http.c.

2730{
2732
2734 HTTP_SERVER_BUCKETS, ast_http_server_hash_fn, NULL, ast_http_server_cmp_fn);
2735 if (!http_servers) {
2737 }
2738
2739 if (__ast_http_load(0)) {
2743 }
2744
2746}
@ 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:2440
static struct ast_cli_entry cli_http[]
Definition: http.c:2692
#define HTTP_SERVER_BUCKETS
Number of HTTP server buckets.
Definition: http.c:2154
@ 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 1530 of file http.c.

1531{
1532 char *parse = ast_strdupa(cookies);
1533 char *cur;
1534 struct ast_variable *vars = NULL, *var;
1535
1536 while ((cur = strsep(&parse, ";"))) {
1537 char *name, *val;
1538
1539 name = val = cur;
1540 strsep(&val, "=");
1541
1543 continue;
1544 }
1545
1546 name = ast_strip(name);
1547 val = ast_strip_quoted(val, "\"", "\"");
1548
1550 continue;
1551 }
1552
1553 ast_debug(1, "HTTP Cookie, Name: '%s' Value: '%s'\n", name, val);
1554
1555 var = ast_variable_new(name, val, __FILE__);
1556 var->next = vars;
1557 vars = var;
1558 }
1559
1560 return vars;
1561}
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 2687 of file http.c.

2688{
2689 return __ast_http_load(1);
2690}

References __ast_http_load().

◆ remove_excess_lws()

static void remove_excess_lws ( char *  s)
static

Definition at line 1735 of file http.c.

1736{
1737 char *p, *res = s;
1738 char *buf = ast_malloc(strlen(s) + 1);
1739 char *buf_end;
1740
1741 if (!buf) {
1742 return;
1743 }
1744
1745 buf_end = buf;
1746
1747 while (*s && *(s = ast_skip_blanks(s))) {
1748 p = s;
1749 s = ast_skip_nonblanks(s);
1750
1751 if (buf_end != buf) {
1752 *buf_end++ = ' ';
1753 }
1754
1755 memcpy(buf_end, p, s - p);
1756 buf_end += s - p;
1757 }
1758 *buf_end = '\0';
1759 /* safe since buf will always be less than or equal to res */
1760 strcpy(res, buf);
1761 ast_free(buf);
1762}

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

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

◆ ast_http_methods_text

const struct ast_cfhttp_methods_text ast_http_methods_text[]
static

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2755 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:2632

Definition at line 2692 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(), create_prefix(), 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 446 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 437 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