Asterisk - The Open Source Telephony Project GIT-master-773870a
Loading...
Searching...
No Matches
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.
 
#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.
 
 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.
 
enum ast_http_method ast_get_http_method_from_string (const char *method)
 Return http method from string.
 
void ast_http_auth (struct ast_tcptls_session_instance *ser, const char *realm, const unsigned long nonce, const unsigned long opaque, int stale, const char *text)
 Send http "401 Unauthorized" response and close socket.
 
int ast_http_body_discard (struct ast_tcptls_session_instance *ser)
 Read and discard any unread HTTP request body.
 
void ast_http_body_read_status (struct ast_tcptls_session_instance *ser, int read_success)
 Update the body read success status.
 
struct ast_variableast_http_create_basic_auth_header (const char *userid, const char *password)
 Create an HTTP authorization header.
 
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.
 
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.
 
const char * ast_http_ftype2mtype (const char *ftype)
 Return mime type based on extension.
 
struct ast_http_authast_http_get_auth (struct ast_variable *headers)
 Get HTTP authentication information from headers.
 
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.
 
struct ast_variableast_http_get_cookies (struct ast_variable *headers)
 Get cookie from Request headers.
 
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.
 
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.
 
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.
 
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.
 
int ast_http_header_parse (char *buf, char **name, char **value)
 Parse a header into the given name/value strings.
 
uint32_t ast_http_manid_from_vars (struct ast_variable *headers)
 Return manager id, if exist, from request headers.
 
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.
 
void ast_http_prefix (char *buf, int len)
 Return the current prefix.
 
void ast_http_request_close_on_completion (struct ast_tcptls_session_instance *ser)
 Request the HTTP connection be closed after this HTTP request.
 
int ast_http_response_status_line (const char *buf, const char *version, int code)
 Parse the http response status line.
 
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.
 
int ast_http_uri_link (struct ast_http_uri *urih)
 Link the new uri into the list.
 
void ast_http_uri_unlink (struct ast_http_uri *urih)
 Unregister a URI handler.
 
void ast_http_uri_unlink_all_with_key (const char *key)
 Unregister all handlers with matching key.
 
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.
 
static char * get_content_type (struct ast_variable *headers)
 Retrieves the content type specified in the "Content-Type" header.
 
static const char * get_header (struct ast_variable *headers, const char *field_name)
 Retrieves the header with the given field name.
 
static const char * get_transfer_encoding (struct ast_variable *headers)
 Returns the value of the Transfer-Encoding header.
 
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.
 
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.
 
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.
 
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.
 
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 void str_append_escaped (struct ast_str **str, const char *in)
 
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 = ASTERISK_GPL_KEY , .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.
 
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 = AST_RWLIST_HEAD_INIT_VALUE
 
static struct uris uris = AST_RWLIST_HEAD_INIT_VALUE
 

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

◆ BASIC_PREFIX

#define BASIC_PREFIX   "Basic "

Definition at line 1645 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 2191 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 1857 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 491 of file http.c.

491 {
492 /*! TRUE if the HTTP request has a body. */
493 HTTP_FLAG_HAS_BODY = (1 << 0),
494 /*! TRUE if the HTTP request body has been read. */
495 HTTP_FLAG_BODY_READ = (1 << 1),
496 /*! TRUE if the HTTP request must close when completed. */
498};
@ HTTP_FLAG_BODY_READ
Definition http.c:495
@ HTTP_FLAG_CLOSE_ON_COMPLETION
Definition http.c:497
@ HTTP_FLAG_HAS_BODY
Definition http.c:493

Function Documentation

◆ __ast_http_load()

static int __ast_http_load ( int  reload)
static

Definition at line 2477 of file http.c.

2478{
2479 struct ast_config *cfg;
2480 struct ast_variable *v;
2481 int enabled = 0;
2482 int new_static_uri_enabled = 0;
2483 int new_status_uri_enabled = 0;
2484 char newprefix[MAX_PREFIX] = "";
2485 char server_name[MAX_SERVER_NAME_LENGTH];
2486 struct http_uri_redirect *redirect;
2487 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2488 uint32_t bindport = DEFAULT_PORT;
2489 int http_tls_was_enabled = 0;
2490 char *bindaddr = NULL;
2491
2492 cfg = ast_config_load2("http.conf", "http", config_flags);
2493 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
2494 return 0;
2495 }
2496
2497 /* Even if the http.conf hasn't been updated, the TLS certs/keys may have been */
2498 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2501 }
2502 return 0;
2503 }
2504
2505 http_tls_was_enabled = (reload && http_tls_cfg.enabled);
2506
2508
2511
2514
2517
2518 /* Apply modern intermediate settings according to the Mozilla OpSec team as of July 30th, 2015 but disable TLSv1 */
2520
2522 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");
2523
2525 while ((redirect = AST_RWLIST_REMOVE_HEAD(&uri_redirects, entry))) {
2526 ast_free(redirect);
2527 }
2529
2531
2535
2536 snprintf(server_name, sizeof(server_name), "Asterisk/%s", ast_get_version());
2537
2538 v = ast_variable_browse(cfg, "general");
2539 for (; v; v = v->next) {
2540 /* read tls config options while preventing unsupported options from being set */
2541 if (strcasecmp(v->name, "tlscafile")
2542 && strcasecmp(v->name, "tlscapath")
2543 && strcasecmp(v->name, "tlscadir")
2544 && strcasecmp(v->name, "tlsverifyclient")
2545 && strcasecmp(v->name, "tlsdontverifyserver")
2546 && strcasecmp(v->name, "tlsclientmethod")
2547 && strcasecmp(v->name, "sslclientmethod")
2549 continue;
2550 }
2551
2552 if (!strcasecmp(v->name, "servername")) {
2553 if (!ast_strlen_zero(v->value)) {
2554 ast_copy_string(server_name, v->value, sizeof(server_name));
2555 } else {
2556 server_name[0] = '\0';
2557 }
2558 } else if (!strcasecmp(v->name, "enabled")) {
2559 enabled = ast_true(v->value);
2560 } else if (!strcasecmp(v->name, "enablestatic") || !strcasecmp(v->name, "enable_static")) {
2561 new_static_uri_enabled = ast_true(v->value);
2562 } else if (!strcasecmp(v->name, "enable_status")) {
2563 new_status_uri_enabled = ast_true(v->value);
2564 } else if (!strcasecmp(v->name, "bindport")) {
2566 &bindport, DEFAULT_PORT, 0, 65535)) {
2567 ast_log(LOG_WARNING, "Invalid port %s specified. Using default port %" PRId32 "\n",
2568 v->value, DEFAULT_PORT);
2569 }
2570 } else if (!strcasecmp(v->name, "bindaddr")) {
2572 } else if (!strcasecmp(v->name, "prefix")) {
2573 if (!ast_strlen_zero(v->value)) {
2574 newprefix[0] = '/';
2575 ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
2576 } else {
2577 newprefix[0] = '\0';
2578 }
2579 } else if (!strcasecmp(v->name, "redirect")) {
2580 add_redirect(v->value);
2581 } else if (!strcasecmp(v->name, "sessionlimit")) {
2583 &session_limit, DEFAULT_SESSION_LIMIT, 1, INT_MAX)) {
2584 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2585 v->name, v->value, v->lineno);
2586 }
2587 } else if (!strcasecmp(v->name, "session_inactivity")) {
2590 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2591 v->name, v->value, v->lineno);
2592 }
2593 } else if (!strcasecmp(v->name, "session_keep_alive")) {
2594 if (sscanf(v->value, "%30d", &session_keep_alive) != 1
2595 || session_keep_alive < 0) {
2597 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
2598 v->name, v->value, v->lineno);
2599 }
2600 } else {
2601 ast_log(LOG_WARNING, "Ignoring unknown option '%s' in http.conf\n", v->name);
2602 }
2603 }
2604
2605 ast_config_destroy(cfg);
2606
2607 if (strcmp(prefix, newprefix)) {
2608 ast_copy_string(prefix, newprefix, sizeof(prefix));
2609 }
2610
2611 ast_copy_string(http_server_name, server_name, sizeof(http_server_name));
2612
2613 if (enabled) {
2614 http_server_get("http server", bindaddr, bindport, &global_http_server);
2615 } else if (global_http_server) {
2618 }
2619
2620 /* When no specific TLS bindaddr is specified, we just use
2621 * the non-TLS bindaddress here.
2622 */
2625
2627 /* Of course, we can't use the same port though.
2628 * Since no bind address was specified, we just use the
2629 * default TLS port
2630 */
2632 }
2633
2634 if (http_tls_was_enabled && !http_tls_cfg.enabled) {
2637 /* We can get here either because a TLS-specific address was specified
2638 * or because we copied the non-TLS address here. In the case where
2639 * we read an explicit address from the config, there may have been
2640 * no port specified, so we'll just use the default TLS port.
2641 */
2644 }
2647 }
2648 }
2649
2650 if (static_uri_enabled && !new_static_uri_enabled) {
2652 } else if (!static_uri_enabled && new_static_uri_enabled) {
2654 }
2655
2656 static_uri_enabled = new_static_uri_enabled;
2657
2658 if (status_uri_enabled && !new_status_uri_enabled) {
2660 } else if (!status_uri_enabled && new_status_uri_enabled) {
2662 }
2663
2664 status_uri_enabled = new_status_uri_enabled;
2665
2666 return 0;
2667}
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
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:2135
int ast_http_uri_link(struct ast_http_uri *urih)
Link the new uri into the list.
Definition http.c:725
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:473
static void http_server_discard(struct ast_http_server *server)
Discard/Drop a HTTP server.
Definition http.c:2280
#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:757
static struct ast_http_uri static_uri
Definition http.c:482
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:2390
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.
#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.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
#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.
#define AST_RWLIST_REMOVE_HEAD
#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:2233
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:220
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
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:71

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

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

2136{
2137 char *target, *dest;
2138 struct http_uri_redirect *redirect, *cur;
2139 unsigned int target_len;
2140 unsigned int total_len;
2141 size_t dest_len;
2142
2145 target = strsep(&dest, " ");
2147 target = strsep(&target, " "); /* trim trailing whitespace */
2148
2149 if (!dest) {
2150 ast_log(LOG_WARNING, "Invalid redirect '%s'\n", value);
2151 return;
2152 }
2153
2154 target_len = strlen(target) + 1;
2155 dest_len = strlen(dest) + 1;
2156 total_len = sizeof(*redirect) + target_len + dest_len;
2157
2158 if (!(redirect = ast_calloc(1, total_len))) {
2159 return;
2160 }
2161 redirect->dest = redirect->target + target_len;
2162 strcpy(redirect->target, target);
2163 ast_copy_string(redirect->dest, dest, dest_len);
2164
2166
2167 target_len--; /* So we can compare directly with strlen() */
2169 || strlen(AST_RWLIST_FIRST(&uri_redirects)->target) <= target_len ) {
2172
2173 return;
2174 }
2175
2177 if (AST_RWLIST_NEXT(cur, entry)
2178 && strlen(AST_RWLIST_NEXT(cur, entry)->target) <= target_len ) {
2181 return;
2182 }
2183 }
2184
2186
2188}
char * strsep(char **str, const char *delims)
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define AST_RWLIST_EMPTY
#define AST_RWLIST_INSERT_AFTER
#define AST_RWLIST_NEXT
#define AST_RWLIST_FIRST
#define AST_RWLIST_TRAVERSE
#define AST_RWLIST_INSERT_HEAD
#define AST_RWLIST_INSERT_TAIL
char *attribute_pure 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
struct http_uri_redirect::@387 entry
char target[0]
Definition http.c:175
int value
Definition syslog.c:37

References ast_calloc, ast_copy_string(), ast_log, AST_RWLIST_EMPTY, AST_RWLIST_FIRST, AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_HEAD, AST_RWLIST_INSERT_TAIL, AST_RWLIST_NEXT, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_skip_blanks(), ast_strdupa, http_uri_redirect::dest, 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:1273
const char * text
Definition http.c:182
#define ARRAY_LEN(a)
Definition utils.h:706

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}
@ 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 674 of file http.c.

677{
678 int status_code = 401;
679 char *status_title = "Unauthorized";
680 struct ast_str *http_header_data = ast_str_create(DEFAULT_RESPONSE_HEADER_LENGTH);
681
682 if (http_header_data) {
683 ast_str_set(&http_header_data,
684 0,
685 "WWW-authenticate: Digest algorithm=MD5, realm=\"%s\", nonce=\"%08lx\", qop=\"auth\", opaque=\"%08lx\"%s\r\n"
686 "Content-type: text/html\r\n",
687 realm ? realm : "Asterisk",
688 nonce,
689 opaque,
690 stale ? ", stale=true" : "");
691 }
692
694 status_code,
695 status_title,
696 http_header_data,
697 text);
698}
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:619
#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.

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

1172{
1174
1175 request = ser->private_data;
1178 /* No body to read or it has already been read. */
1179 return 0;
1180 }
1182
1183 ast_debug(1, "HTTP discarding unused request body\n");
1184
1185 ast_assert(request->body_length != 0);
1186 if (0 < request->body_length) {
1187 if (http_body_discard_contents(ser, request->body_length, "body")) {
1189 return -1;
1190 }
1191 return 0;
1192 }
1193
1194 /* parse chunked-body */
1195 for (;;) {
1196 int length;
1197
1198 length = http_body_get_chunk_length(ser);
1199 if (length < 0) {
1201 return -1;
1202 }
1203 if (length == 0) {
1204 /* parsed last-chunk */
1205 break;
1206 }
1207
1208 if (http_body_discard_contents(ser, length, "chunk-data")
1211 return -1;
1212 }
1213 }
1214
1215 /* Read and discard any trailer entity-header lines. */
1218 return -1;
1219 }
1220 return 0;
1221}
static int request(void *obj)
static int http_body_discard_chunk_trailer_headers(struct ast_tcptls_session_instance *ser)
Definition http.c:1151
static int http_body_discard_contents(struct ast_tcptls_session_instance *ser, int length, const char *what_getting)
Definition http.c:1015
static int http_body_check_chunk_sync(struct ast_tcptls_session_instance *ser)
Definition http.c:1120
static int http_body_get_chunk_length(struct ast_tcptls_session_instance *ser)
Definition http.c:1092
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_test_flag(p, flag)
Definition utils.h:64
#define ast_assert(a)
Definition utils.h:779

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

951{
953
954 request = ser->private_data;
957 /* No body to read. */
958 return;
959 }
961 if (!read_success) {
963 }
964}

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

1707{
1708 int encoded_size = 0;
1709 int userinfo_len = 0;
1710 RAII_VAR(char *, userinfo, NULL, ast_free);
1711 char *encoded_userinfo = NULL;
1712 struct ast_variable *auth_header = NULL;
1713
1714 if (ast_strlen_zero(userid)) {
1715 return NULL;
1716 }
1717
1718 if (strchr(userid, ':')) {
1719 userinfo = ast_strdup(userid);
1720 userinfo_len = strlen(userinfo);
1721 } else {
1722 if (ast_strlen_zero(password)) {
1723 return NULL;
1724 }
1725 userinfo_len = ast_asprintf(&userinfo, "%s:%s", userid, password);
1726 }
1727 if (!userinfo) {
1728 return NULL;
1729 }
1730
1731 /*
1732 * The header value is "Basic " + base64(userinfo).
1733 * Doubling the userinfo length then adding the length
1734 * of the "Basic " prefix is a conservative estimate of the
1735 * final encoded size.
1736 */
1737 encoded_size = userinfo_len * 2 * sizeof(char) + 1 + BASIC_LEN;
1738 encoded_userinfo = ast_alloca(encoded_size);
1739 strcpy(encoded_userinfo, BASIC_PREFIX); /* Safe */
1740 ast_base64encode(encoded_userinfo + BASIC_LEN, (unsigned char *)userinfo,
1741 userinfo_len, encoded_size - BASIC_LEN);
1742
1743 auth_header = ast_variable_new("Authorization",
1744 encoded_userinfo, "");
1745
1746 return auth_header;
1747}
#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:1645
#define BASIC_LEN
Definition http.c:1646
#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:981
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition utils.c:404

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 outbound_session_handler_thread(), and 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 619 of file http.c.

621{
622 char server_name[MAX_SERVER_NAME_LENGTH];
623 struct ast_str *server_address = ast_str_create(MAX_SERVER_NAME_LENGTH);
625
626 if (!http_header_data || !server_address || !out) {
627 ast_free(http_header_data);
628 ast_free(server_address);
629 ast_free(out);
630 if (ser) {
631 ast_debug(1, "HTTP closing session. OOM.\n");
633 }
634 return;
635 }
636
638 ast_xml_escape(http_server_name, server_name, sizeof(server_name));
639 ast_str_set(&server_address,
640 0,
641 "<address>%s</address>\r\n",
642 server_name);
643 }
644
646 0,
647 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
648 "<html><head>\r\n"
649 "<title>%d %s</title>\r\n"
650 "</head><body>\r\n"
651 "<h1>%s</h1>\r\n"
652 "<p>%s</p>\r\n"
653 "<hr />\r\n"
654 "%s"
655 "</body></html>\r\n",
656 status_code,
657 status_title,
658 status_title,
659 text ? text : "",
660 ast_str_buffer(server_address));
661
662 ast_free(server_address);
663
664 ast_http_send(ser,
666 status_code,
667 status_title,
668 http_header_data,
669 out,
670 0,
671 0);
672}
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:508
#define INITIAL_RESPONSE_BODY_BUFFER
Definition http.c:92
char *attribute_pure 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:898

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

702{
703 struct ast_str *http_header_data = ast_str_create(DEFAULT_RESPONSE_HEADER_LENGTH);
704
705 if (http_header_data) {
706 ast_str_set(&http_header_data, 0, "Content-type: text/html\r\n");
707 }
708
710 status_code,
711 status_title,
712 http_header_data,
713 text);
714}

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

Referenced by 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(), incoming_ws_http_callback(), phoneprov_callback(), static_callback(), 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 @386 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 1648 of file http.c.

1649{
1650 struct ast_variable *v;
1651
1652 for (v = headers; v; v = v->next) {
1653 const char *base64;
1654 char decoded[256] = {};
1655 char *username;
1656 char *password;
1657#ifdef AST_DEVMODE
1658 int cnt;
1659#endif /* AST_DEVMODE */
1660
1661 if (strcasecmp("Authorization", v->name) != 0) {
1662 continue;
1663 }
1664
1667 "Unsupported Authorization scheme\n");
1668 continue;
1669 }
1670
1671 /* Basic auth header parsing. RFC 2617, section 2.
1672 * credentials = "Basic" basic-credentials
1673 * basic-credentials = base64-user-pass
1674 * base64-user-pass = <base64 encoding of user-pass,
1675 * except not limited to 76 char/line>
1676 * user-pass = userid ":" password
1677 */
1678
1679 base64 = v->value + BASIC_LEN;
1680
1681 /* This will truncate "userid:password" lines to
1682 * sizeof(decoded). The array is long enough that this shouldn't
1683 * be a problem */
1684#ifdef AST_DEVMODE
1685 cnt =
1686#endif /* AST_DEVMODE */
1687 ast_base64decode((unsigned char*)decoded, base64,
1688 sizeof(decoded) - 1);
1689 ast_assert(cnt < sizeof(decoded));
1690
1691 /* Split the string at the colon */
1692 password = decoded;
1693 username = strsep(&password, ":");
1694 if (!password) {
1695 ast_log(LOG_WARNING, "Invalid Authorization header\n");
1696 return NULL;
1697 }
1698
1699 return auth_create(username, password);
1700 }
1701
1702 return NULL;
1703}
static struct ast_http_auth * auth_create(const char *userid, const char *password)
Definition http.c:1614
#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 1233 of file http.c.

1235{
1237 int content_length;
1238 int bufsize;
1239 char *buf;
1240
1241 request = ser->private_data;
1242 if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)) {
1243 /* no content - not an error */
1244 return NULL;
1245 }
1247 /* Already read the body. Cannot read again. Assume no content. */
1248 ast_assert(0);
1249 return NULL;
1250 }
1252
1253 ast_debug(2, "HTTP consuming request body\n");
1254
1255 ast_assert(request->body_length != 0);
1256 if (0 < request->body_length) {
1257 /* handle regular non-chunked content */
1258 content_length = request->body_length;
1259 if (content_length > MAX_CONTENT_LENGTH) {
1260 ast_log(LOG_WARNING, "Excessively long HTTP content. (%d > %d)\n",
1261 content_length, MAX_CONTENT_LENGTH);
1263 errno = EFBIG;
1264 return NULL;
1265 }
1266 buf = ast_malloc(content_length + 1);
1267 if (!buf) {
1268 /* Malloc sets ENOMEM */
1270 return NULL;
1271 }
1272
1273 if (http_body_read_contents(ser, buf, content_length, "body")) {
1275 errno = EIO;
1276 ast_free(buf);
1277 return NULL;
1278 }
1279
1280 buf[content_length] = 0;
1281 *return_length = content_length;
1282 return buf;
1283 }
1284
1285 /* pre-allocate buffer */
1286 bufsize = 250;
1287 buf = ast_malloc(bufsize);
1288 if (!buf) {
1290 return NULL;
1291 }
1292
1293 /* parse chunked-body */
1294 content_length = 0;
1295 for (;;) {
1296 int chunk_length;
1297
1298 chunk_length = http_body_get_chunk_length(ser);
1299 if (chunk_length < 0) {
1301 errno = EIO;
1302 ast_free(buf);
1303 return NULL;
1304 }
1305 if (chunk_length == 0) {
1306 /* parsed last-chunk */
1307 break;
1308 }
1309 if (content_length + chunk_length > MAX_CONTENT_LENGTH) {
1311 "Excessively long HTTP accumulated chunked body. (%d + %d > %d)\n",
1312 content_length, chunk_length, MAX_CONTENT_LENGTH);
1314 errno = EFBIG;
1315 ast_free(buf);
1316 return NULL;
1317 }
1318
1319 /* insure buffer is large enough +1 */
1320 if (content_length + chunk_length >= bufsize) {
1321 char *new_buf;
1322
1323 /* Increase bufsize until it can handle the expected data. */
1324 do {
1325 bufsize *= 2;
1326 } while (content_length + chunk_length >= bufsize);
1327
1328 new_buf = ast_realloc(buf, bufsize);
1329 if (!new_buf) {
1331 ast_free(buf);
1332 return NULL;
1333 }
1334 buf = new_buf;
1335 }
1336
1337 if (http_body_read_contents(ser, buf + content_length, chunk_length, "chunk-data")
1340 errno = EIO;
1341 ast_free(buf);
1342 return NULL;
1343 }
1344 content_length += chunk_length;
1345 }
1346
1347 /*
1348 * Read and discard any trailer entity-header lines
1349 * which we don't care about.
1350 *
1351 * XXX In the future we may need to add the trailer headers
1352 * to the passed in headers list rather than discarding them.
1353 */
1356 errno = EIO;
1357 ast_free(buf);
1358 return NULL;
1359 }
1360
1361 buf[content_length] = 0;
1362 *return_length = content_length;
1363 return buf;
1364}
#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:979
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 1601 of file http.c.

1602{
1603 struct ast_variable *v, *cookies = NULL;
1604
1605 for (v = headers; v; v = v->next) {
1606 if (!strcasecmp(v->name, "Cookie")) {
1607 ast_variables_destroy(cookies);
1608 cookies = parse_cookies(v->value);
1609 }
1610 }
1611 return cookies;
1612}
static struct ast_variable * parse_cookies(const char *cookies)
Definition http.c:1567
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition extconf.c:1260

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

1368{
1369 int content_length = 0;
1370 struct ast_json *body;
1371 RAII_VAR(char *, buf, NULL, ast_free);
1372 RAII_VAR(char *, type, get_content_type(headers), ast_free);
1373
1374 /* Use errno to distinguish errors from no body */
1375 errno = 0;
1376
1377 if (ast_strlen_zero(type) || strcasecmp(type, "application/json")) {
1378 /* Content type is not JSON. Don't read the body. */
1379 return NULL;
1380 }
1381
1382 buf = ast_http_get_contents(&content_length, ser, headers);
1383 if (!buf || !content_length) {
1384 /*
1385 * errno already set
1386 * or it is not an error to have zero content
1387 */
1388 return NULL;
1389 }
1390
1391 body = ast_json_load_buf(buf, content_length, NULL);
1392 if (!body) {
1393 /* Failed to parse JSON; treat as an I/O error */
1394 errno = EIO;
1395 return NULL;
1396 }
1397
1398 return body;
1399}
static const char type[]
static char * get_content_type(struct ast_variable *headers)
Retrieves the content type specified in the "Content-Type" header.
Definition http.c:814
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:1233
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 1441 of file http.c.

1443{
1444 int content_length = 0;
1445 RAII_VAR(char *, buf, NULL, ast_free);
1446 RAII_VAR(char *, type, get_content_type(headers), ast_free);
1447
1448 /* Use errno to distinguish errors from no params */
1449 errno = 0;
1450
1451 if (ast_strlen_zero(type) ||
1452 strcasecmp(type, "application/x-www-form-urlencoded")) {
1453 /* Content type is not form data. Don't read the body. */
1454 return NULL;
1455 }
1456
1457 buf = ast_http_get_contents(&content_length, ser, headers);
1458 if (!buf || !content_length) {
1459 /*
1460 * errno already set
1461 * or it is not an error to have zero content
1462 */
1463 return NULL;
1464 }
1465
1466 return ast_http_parse_post_form(buf, content_length, type);
1467}
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:1405

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

1825{
1826 if (strcasecmp(name, expected_name)) {
1827 /* no value to validate if names don't match */
1828 return 0;
1829 }
1830
1831 if (strcasecmp(value, expected_value)) {
1832 ast_log(LOG_ERROR, "Invalid header value - expected %s "
1833 "received %s", value, expected_value);
1834 return -1;
1835 }
1836 return 1;
1837}
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 1839 of file http.c.

1841{
1842 if (strcasecmp(name, expected_name)) {
1843 /* no value to validate if names don't match */
1844 return 0;
1845 }
1846
1847 if (!strcasestr(expected_value, value)) {
1848 ast_log(LOG_ERROR, "Header '%s' - could not locate '%s' "
1849 "in '%s'\n", name, value, expected_value);
1850 return -1;
1851
1852 }
1853 return 1;
1854}
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 1801 of file http.c.

1802{
1804 if (ast_strlen_zero(buf)) {
1805 return -1;
1806 }
1807
1808 *value = buf;
1809 *name = strsep(value, ":");
1810 if (!*value) {
1811 return 1;
1812 }
1813
1816 return 1;
1817 }
1818
1820 return 0;
1821}
static void remove_excess_lws(char *s)
Definition http.c:1772
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:1601

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

1407{
1408 struct ast_variable *v, *post_vars=NULL, *prev = NULL;
1409 char *var, *val;
1410
1411 /* Use errno to distinguish errors from no params */
1412 errno = 0;
1413
1414 if (ast_strlen_zero(content_type) ||
1415 strcasecmp(content_type, "application/x-www-form-urlencoded") != 0) {
1416 /* Content type is not form data. Don't read the body. */
1417 return NULL;
1418 }
1419
1420 while ((val = strsep(&buf, "&"))) {
1421 var = strsep(&val, "=");
1422 if (val) {
1424 } else {
1425 val = "";
1426 }
1428 if ((v = ast_variable_new(var, val, ""))) {
1429 if (post_vars) {
1430 prev->next = v;
1431 } else {
1432 post_vars = v;
1433 }
1434 prev = v;
1435 }
1436 }
1437
1438 return post_vars;
1439}
#define var
Definition ast_expr2f.c:605
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Definition utils.c:760
const struct ast_flags ast_uri_http_legacy
Definition utils.c:718

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

1750{
1751 int status_code;
1752 size_t size = strlen(version);
1753
1754 if (strncmp(buf, version, size) || buf[size] != ' ') {
1755 ast_log(LOG_ERROR, "HTTP version not supported - "
1756 "expected %s\n", version);
1757 return -1;
1758 }
1759
1760 /* skip to status code (version + space) */
1761 buf += size + 1;
1762
1763 if (sscanf(buf, "%d", &status_code) != 1) {
1764 ast_log(LOG_ERROR, "Could not read HTTP status code - "
1765 "%s\n", buf);
1766 return -1;
1767 }
1768
1769 return status_code;
1770}
static char version[AST_MAX_EXTENSION]

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

512{
513 struct timeval now = ast_tvnow();
514 struct ast_tm tm;
515 char timebuf[80];
516 char buf[256];
517 int len;
518 int content_length = 0;
519 int close_connection;
520 struct ast_str *server_header_field = ast_str_create(MAX_SERVER_NAME_LENGTH);
521 int send_content;
522
523 if (!ser || !server_header_field) {
524 /* The connection is not open. */
525 ast_free(http_header);
526 ast_free(out);
527 ast_free(server_header_field);
528 return;
529 }
530
532 ast_str_set(&server_header_field,
533 0,
534 "Server: %s\r\n",
536 }
537
538 /*
539 * We shouldn't be sending non-final status codes to this
540 * function because we may close the connection before
541 * returning.
542 */
543 ast_assert(200 <= status_code);
544
545 if (session_keep_alive <= 0) {
546 close_connection = 1;
547 } else {
549
550 request = ser->private_data;
551 if (!request
553 || ast_http_body_discard(ser)) {
554 close_connection = 1;
555 } else {
556 close_connection = 0;
557 }
558 }
559
560 ast_strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", ast_localtime(&now, &tm, "GMT"));
561
562 /* calc content length */
563 if (out) {
564 content_length += ast_str_strlen(out);
565 }
566
567 if (fd) {
568 content_length += lseek(fd, 0, SEEK_END);
569 lseek(fd, 0, SEEK_SET);
570 }
571
572 send_content = method != AST_HTTP_HEAD || status_code >= 400;
573
574 /* send http header */
576 "HTTP/1.1 %d %s\r\n"
577 "%s"
578 "Date: %s\r\n"
579 "%s"
580 "%s"
581 "%s"
582 "Content-Length: %d\r\n"
583 "\r\n"
584 "%s",
585 status_code, status_title ? status_title : "OK",
586 ast_str_buffer(server_header_field),
587 timebuf,
588 close_connection ? "Connection: close\r\n" : "",
589 static_content ? "" : "Cache-Control: no-cache, no-store\r\n",
590 http_header ? ast_str_buffer(http_header) : "",
591 content_length,
592 send_content && out && ast_str_strlen(out) ? ast_str_buffer(out) : ""
593 ) <= 0) {
594 ast_debug(1, "ast_iostream_printf() failed: %s\n", strerror(errno));
595 close_connection = 1;
596 } else if (send_content && fd) {
597 /* send file content */
598 while ((len = read(fd, buf, sizeof(buf))) > 0) {
599 if (ast_iostream_write(ser->stream, buf, len) != len) {
600 ast_debug(1, "ast_iostream_write() failed: %s\n", strerror(errno));
601 close_connection = 1;
602 break;
603 }
604 }
605 }
606
607 ast_free(http_header);
608 ast_free(out);
609 ast_free(server_header_field);
610
611 if (close_connection) {
612 ast_debug(1, "HTTP closing session. status_code:%d\n", status_code);
614 } else {
615 ast_debug(1, "HTTP keeping session open. status_code:%d\n", status_code);
616 }
617}
int ast_http_body_discard(struct ast_tcptls_session_instance *ser)
Read and discard any unread HTTP request body.
Definition http.c:1171
@ 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 attribute_pure 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(), 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 725 of file http.c.

726{
727 struct ast_http_uri *uri;
728 int len = strlen(urih->uri);
729
731
732 urih->prefix = prefix;
733
734 if ( AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len ) {
737 return 0;
738 }
739
741 if (AST_RWLIST_NEXT(uri, entry) &&
742 strlen(AST_RWLIST_NEXT(uri, entry)->uri) <= len) {
745
746 return 0;
747 }
748 }
749
751
753
754 return 0;
755}
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::@241 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(), load_module(), load_module(), load_module(), load_module(), load_module(), reload_module(), and reload_module().

◆ ast_http_uri_unlink()

void ast_http_uri_unlink ( struct ast_http_uri urih)

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

765{
766 struct ast_http_uri *urih;
769 if (!strcmp(urih->key, key)) {
771 if (urih->dmallocd) {
772 ast_free(urih->data);
773 }
774 if (urih->mallocd) {
775 ast_free(urih);
776 }
777 }
778 }
781}
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_TRAVERSE_SAFE_END
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 2792 of file http.c.

◆ auth_create()

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

Definition at line 1614 of file http.c.

1615{
1616 struct ast_http_auth *auth;
1617 size_t userid_len;
1618 size_t password_len;
1619
1620 if (!userid || !password) {
1621 ast_log(LOG_ERROR, "Invalid userid/password\n");
1622 return NULL;
1623 }
1624
1625 userid_len = strlen(userid) + 1;
1626 password_len = strlen(password) + 1;
1627
1628 /* Allocate enough room to store everything in one memory block */
1629 auth = ao2_alloc(sizeof(*auth) + userid_len + password_len, NULL);
1630 if (!auth) {
1631 return NULL;
1632 }
1633
1634 /* Put the userid right after the struct */
1635 auth->userid = (char *)(auth + 1);
1636 strcpy(auth->userid, userid);
1637
1638 /* Put the password right after the userid */
1639 auth->password = auth->userid + userid_len;
1640 strcpy(auth->password, password);
1641
1642 return auth;
1643}
#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 1038 of file http.c.

1039{
1040 int value = 0;
1041 char c;
1042
1043 if (*s < '0') {
1044 /* zero value must be 0\n not just \n */
1045 return -1;
1046 }
1047
1048 while (len--) {
1049 c = *s++;
1050 if (c == '\x0D') {
1051 return value;
1052 }
1053 if (c == ';') {
1054 /* We have a chunk-extension that we don't care about. */
1055 while (len--) {
1056 if (*s++ == '\x0D') {
1057 return value;
1058 }
1059 }
1060 break;
1061 }
1062 value <<= 4;
1063 if (c >= '0' && c <= '9') {
1064 value += c - '0';
1065 continue;
1066 }
1067 if (c >= 'a' && c <= 'f') {
1068 value += 10 + c - 'a';
1069 continue;
1070 }
1071 if (c >= 'A' && c <= 'F') {
1072 value += 10 + c - 'A';
1073 continue;
1074 }
1075 /* invalid character */
1076 return -1;
1077 }
1078 /* end of string */
1079 return -1;
1080}
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 839 of file http.c.

840{
841 const char *content_length = get_header(headers, "Content-Length");
842 int length;
843
844 if (!content_length) {
845 /* Missing content length; assume zero */
846 return 0;
847 }
848
849 length = 0;
850 if (sscanf(content_length, "%30d", &length) != 1) {
851 /* Invalid Content-Length value */
852 length = -1;
853 }
854 return length;
855}
static const char * get_header(struct ast_variable *headers, const char *field_name)
Retrieves the header with the given field name.
Definition http.c:791

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

815{
816 const char *content_type = get_header(headers, "Content-Type");
817 const char *param;
818 size_t size;
819
820 if (!content_type) {
821 return NULL;
822 }
823
824 param = strchr(content_type, ';');
825 size = param ? param - content_type : strlen(content_type);
826
827 return ast_strndup(content_type, size);
828}
#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 791 of file http.c.

792{
793 struct ast_variable *v;
794
795 for (v = headers; v; v = v->next) {
796 if (!strcasecmp(v->name, field_name)) {
797 return v->value;
798 }
799 }
800 return NULL;
801}

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

865{
866 return get_header(headers, "Transfer-Encoding");
867}

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

2670{
2671 struct ast_http_uri *urih;
2672 struct http_uri_redirect *redirect;
2673
2674 switch (cmd) {
2675 case CLI_INIT:
2676 e->command = "http show status";
2677 e->usage =
2678 "Usage: http show status\n"
2679 " Lists status of internal HTTP engine\n";
2680 return NULL;
2681 case CLI_GENERATE:
2682 return NULL;
2683 }
2684
2685 if (a->argc != 3) {
2686 return CLI_SHOWUSAGE;
2687 }
2688 ast_cli(a->fd, "HTTP Server Status:\n");
2689 ast_cli(a->fd, "Prefix: %s\n", prefix);
2690 ast_cli(a->fd, "Server: %s\n", http_server_name);
2691 if (!global_http_server) {
2692 ast_cli(a->fd, "Server Disabled\n\n");
2693 } else {
2694 ast_cli(a->fd, "Server Enabled and Bound to %s\n\n",
2696 if (http_tls_cfg.enabled) {
2697 ast_cli(a->fd, "HTTPS Server Enabled and Bound to %s\n\n",
2699 }
2700 }
2701
2702 ast_cli(a->fd, "Enabled URI's:\n");
2704 if (AST_RWLIST_EMPTY(&uris)) {
2705 ast_cli(a->fd, "None.\n");
2706 } else {
2708 ast_cli(a->fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
2709 }
2711
2712 ast_cli(a->fd, "\nEnabled Redirects:\n");
2715 ast_cli(a->fd, " %s => %s\n", redirect->target, redirect->dest);
2717 ast_cli(a->fd, " None.\n");
2718 }
2720
2721 return CLI_SUCCESS;
2722}
#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
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 1469 of file http.c.

1471{
1472 char *c;
1473 int res = 0;
1474 char *params = uri;
1475 struct ast_http_uri *urih = NULL;
1476 int l;
1477 struct ast_variable *get_vars = NULL, *v, *prev = NULL;
1478 struct http_uri_redirect *redirect;
1479
1480 ast_debug(2, "HTTP Request URI is %s \n", uri);
1481
1482 strsep(&params, "?");
1483 /* Extract arguments from the request and store them in variables. */
1484 if (params) {
1485 char *var, *val;
1486
1487 while ((val = strsep(&params, "&"))) {
1488 var = strsep(&val, "=");
1489 if (val) {
1491 } else {
1492 val = "";
1493 }
1495 if ((v = ast_variable_new(var, val, ""))) {
1496 if (get_vars) {
1497 prev->next = v;
1498 } else {
1499 get_vars = v;
1500 }
1501 prev = v;
1502 }
1503 }
1504 }
1505
1508 if (!strcasecmp(uri, redirect->target)) {
1509 struct ast_str *http_header = ast_str_create(128);
1510
1511 if (!http_header) {
1513 ast_http_error(ser, 500, "Server Error", "Out of memory");
1514 break;
1515 }
1516 ast_str_set(&http_header, 0, "Location: %s\r\n", redirect->dest);
1517 ast_http_send(ser, method, 302, "Moved Temporarily", http_header, NULL, 0, 0);
1518 break;
1519 }
1520 }
1522 if (redirect) {
1523 goto cleanup;
1524 }
1525
1526 /* We want requests to start with the (optional) prefix and '/' */
1527 l = strlen(prefix);
1528 if (!strncasecmp(uri, prefix, l) && uri[l] == '/') {
1529 uri += l + 1;
1530 /* scan registered uris to see if we match one. */
1532 AST_RWLIST_TRAVERSE(&uris, urih, entry) {
1533 l = strlen(urih->uri);
1534 c = uri + l; /* candidate */
1535 ast_debug(2, "match request [%s] with handler [%s] len %d\n", uri, urih->uri, l);
1536 if (strncasecmp(urih->uri, uri, l) /* no match */
1537 || (*c && *c != '/')) { /* substring */
1538 continue;
1539 }
1540 if (*c == '/') {
1541 c++;
1542 }
1543 if (!*c || urih->has_subtree) {
1544 uri = c;
1545 break;
1546 }
1547 }
1549 }
1550 if (urih) {
1551 ast_debug(1, "Match made with [%s]\n", urih->uri);
1552 if (!urih->no_decode_uri) {
1554 }
1555 res = urih->callback(ser, urih, uri, method, get_vars, headers);
1556 } else {
1557 ast_debug(1, "Request from %s for URI [%s] has no registered handler\n",
1559 ast_http_error(ser, 404, "Not Found", "The requested URL was not found on this server.");
1560 }
1561
1562cleanup:
1563 ast_variables_destroy(get_vars);
1564 return res;
1565}
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:700
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:889
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Definition netsock2.h:286
static void cleanup(void)
Clean up any old apps that we don't need any more.
Definition res_stasis.c:327
unsigned int no_decode_uri
Definition http.h:114
ast_http_callback callback
Definition http.h:107
struct ast_sockaddr remote_address
Definition tcptls.h:153

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_sockaddr_stringify_addr(), 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, ast_tcptls_session_instance::remote_address, 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 1120 of file http.c.

1121{
1122 int res;
1123 char chunk_sync[2];
1124
1125 /* Stay in fread until get the expected CRLF or timeout. */
1126 res = ast_iostream_read(ser->stream, chunk_sync, sizeof(chunk_sync));
1127 if (res < sizeof(chunk_sync)) {
1128 ast_log(LOG_WARNING, "Short HTTP chunk sync read (Wanted %zu)\n",
1129 sizeof(chunk_sync));
1130 return -1;
1131 }
1132 if (chunk_sync[0] != 0x0D || chunk_sync[1] != 0x0A) {
1133 ast_log(LOG_WARNING, "HTTP chunk sync bytes wrong (0x%02hhX, 0x%02hhX)\n",
1134 (unsigned char) chunk_sync[0], (unsigned char) chunk_sync[1]);
1135 return -1;
1136 }
1137
1138 return 0;
1139}
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 1151 of file http.c.

1152{
1153 char header_line[MAX_HTTP_LINE_LENGTH];
1154
1155 for (;;) {
1156 if (ast_iostream_gets(ser->stream, header_line, sizeof(header_line)) <= 0) {
1157 ast_log(LOG_WARNING, "Short HTTP read of chunked trailer header\n");
1158 return -1;
1159 }
1160
1161 /* Trim trailing whitespace */
1162 ast_trim_blanks(header_line);
1163 if (ast_strlen_zero(header_line)) {
1164 /* A blank line ends the chunked-body */
1165 break;
1166 }
1167 }
1168 return 0;
1169}
#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 1015 of file http.c.

1016{
1017 ssize_t res;
1018
1019 res = ast_iostream_discard(ser->stream, length);
1020 if (res < length) {
1021 ast_log(LOG_WARNING, "Short HTTP request %s (Wanted %d but got %zd)\n",
1022 what_getting, length, res);
1023 return -1;
1024 }
1025 return 0;
1026}
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 1092 of file http.c.

1093{
1094 int length;
1095 char header_line[MAX_HTTP_LINE_LENGTH];
1096
1097 /* get the line of hexadecimal giving chunk-size w/ optional chunk-extension */
1098 if (ast_iostream_gets(ser->stream, header_line, sizeof(header_line)) <= 0) {
1099 ast_log(LOG_WARNING, "Short HTTP read of chunked header\n");
1100 return -1;
1101 }
1102 length = chunked_atoh(header_line, strlen(header_line));
1103 if (length < 0) {
1104 ast_log(LOG_WARNING, "Invalid HTTP chunk size\n");
1105 return -1;
1106 }
1107 return length;
1108}
static int chunked_atoh(const char *s, int len)
Definition http.c:1038

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

980{
981 int res;
982 int total = 0;
983
984 /* Stream is in exclusive mode so we get it all if possible. */
985 while (total != length) {
986 res = ast_iostream_read(ser->stream, buf + total, length - total);
987 if (res <= 0) {
988 break;
989 }
990
991 total += res;
992 }
993
994 if (total != length) {
995 ast_log(LOG_WARNING, "Wrong HTTP content read. Request %s (Wanted %d, Read %d)\n",
996 what_getting, length, res);
997 return -1;
998 }
999
1000 return 0;
1001}
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 878 of file http.c.

879{
880 const char *connection = get_header(headers, "Connection");
881 int close_connection = 0;
882
883 if (connection && !strcasecmp(connection, "close")) {
884 close_connection = -1;
885 }
886 return close_connection;
887}

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

1871{
1872 struct ast_variable *tail = *headers;
1873 int remaining_headers;
1874 char header_line[MAX_HTTP_LINE_LENGTH];
1875
1876 remaining_headers = MAX_HTTP_REQUEST_HEADERS;
1877 for (;;) {
1878 ssize_t len;
1879 char *name;
1880 char *value;
1881
1882 len = ast_iostream_gets(ser->stream, header_line, sizeof(header_line));
1883 if (len <= 0) {
1884 ast_http_error(ser, 400, "Bad Request", "Timeout");
1885 return -1;
1886 }
1887 if (header_line[len - 1] != '\n') {
1888 /* We didn't get a full line */
1889 ast_http_error(ser, 400, "Bad Request",
1890 (len == sizeof(header_line) - 1) ? "Header line too long" : "Timeout");
1891 return -1;
1892 }
1893
1894 /* Trim trailing characters */
1895 ast_trim_blanks(header_line);
1896 if (ast_strlen_zero(header_line)) {
1897 /* A blank line ends the request header section. */
1898 break;
1899 }
1900
1901 value = header_line;
1902 name = strsep(&value, ":");
1903 if (!value) {
1904 continue;
1905 }
1906
1909 continue;
1910 }
1911
1913
1914 if (!remaining_headers--) {
1915 /* Too many headers. */
1916 ast_http_error(ser, 413, "Request Entity Too Large", "Too many headers");
1917 return -1;
1918 }
1919 if (!*headers) {
1920 *headers = ast_variable_new(name, value, __FILE__);
1921 tail = *headers;
1922 } else {
1923 tail->next = ast_variable_new(name, value, __FILE__);
1924 tail = tail->next;
1925 }
1926 if (!tail) {
1927 /*
1928 * Variable allocation failure.
1929 * Try to make some room.
1930 */
1931 ast_variables_destroy(*headers);
1932 *headers = NULL;
1933
1934 ast_http_error(ser, 500, "Server Error", "Out of memory");
1935 return -1;
1936 }
1937 }
1938
1939 return 0;
1940}
#define MAX_HTTP_REQUEST_HEADERS
Definition http.c:1857

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

904{
907 /* Assume close in case request fails early */
909}
#define ast_set_flags_to(p, flag, value)
Definition utils.h:105

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

923{
925 const char *transfer_encoding;
926
930
931 transfer_encoding = get_transfer_encoding(headers);
932 if (transfer_encoding && !strcasecmp(transfer_encoding, "chunked")) {
933 request->body_length = -1;
935 return 0;
936 }
937
938 request->body_length = get_content_length(headers);
939 if (0 < request->body_length) {
941 } else if (request->body_length < 0) {
942 /* Invalid Content-Length */
944 ast_http_error(ser, 400, "Bad Request", "Invalid Content-Length in request!");
945 return -1;
946 }
947 return 0;
948}
static int http_check_connection_close(struct ast_variable *headers)
Definition http.c:878
static const char * get_transfer_encoding(struct ast_variable *headers)
Returns the value of the Transfer-Encoding header.
Definition http.c:864
static int get_content_length(struct ast_variable *headers)
Returns the value of the Content-Length header.
Definition http.c:839

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

2212{
2213 struct ast_http_server *server;
2214
2215 server = ao2_alloc(sizeof(*server), http_server_destroy);
2216 if (!server) {
2217 ast_log(LOG_ERROR, "Unable to allocate HTTP server '%s' at address '%s'\n",
2218 name, address);
2219 return NULL;
2220 }
2221
2222 if (!(server->address = ast_strdup(address)) || !(server->name = ast_strdup(name))) {
2223 ast_log(LOG_ERROR, "Unable to complete setup for HTTP server '%s' at address '%s'\n",
2224 name, address);
2225 ao2_ref(server, -1);
2226 return NULL;
2227 }
2228
2229 server->args.accept_fd = -1;
2230 server->args.master = AST_PTHREADT_NULL;
2231 server->args.tls_cfg = NULL;
2232 server->args.poll_timeout = -1;
2233 server->args.name = server->name;
2236
2237 ast_sockaddr_copy(&server->args.local_address, addr);
2238
2239 return server;
2240}
#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:2050
static void http_server_destroy(void *obj)
Definition http.c:2198
#define AST_PTHREADT_NULL
Definition lock.h:73
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 2198 of file http.c.

2199{
2200 struct ast_http_server *server = obj;
2201
2202 ast_tcptls_server_stop(&server->args);
2203
2204 ast_verb(1, "Stopped http server '%s' listening at '%s'\n", server->name, server->address);
2205
2206 ast_free(server->name);
2207 ast_free(server->address);
2208}
#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 2280 of file http.c.

2281{
2282 if (!server) {
2283 return;
2284 }
2285
2286 /*
2287 * If only two references were on the object then the last one is from
2288 * the servers container, so remove from container now.
2289 */
2290 if (ao2_ref(server, -1) == 2) {
2291 ao2_unlink(http_servers, server);
2292 }
2293}
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition astobj2.h:1578
struct ao2_container * http_servers
Definition http.c:2193

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

2392{
2393 struct ast_http_server *server;
2394
2396
2397 server = http_server_get_by_host(name, host, port);
2398
2399 if (replace_me) {
2400 /* Only replace if different */
2401 if (*replace_me == server) {
2402 ao2_cleanup(server);
2404 return *replace_me;
2405 }
2406
2407 if (*replace_me) {
2408 http_server_discard(*replace_me);
2409 }
2410
2411 *replace_me = server;
2412 }
2413
2414 if (server && http_server_start(server)) {
2415 if (replace_me) {
2416 *replace_me = NULL;
2417 }
2418
2419 ao2_ref(server, -1);
2420 server = NULL;
2421 }
2422
2424 return server;
2425}
#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:2242
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:2338

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

2310{
2311 struct ast_http_server *server;
2312 const char *address;
2313
2315 if (ast_strlen_zero(address)) {
2316 return NULL;
2317 }
2318
2320
2321 return server ?: http_server_create(name, address, addr);
2322}
#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:2210

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

2340{
2341 struct ast_sockaddr *addrs = NULL;
2342 int num_addrs;
2343 int i;
2344
2345 if (!(num_addrs = ast_sockaddr_resolve(&addrs, host, 0, AST_AF_UNSPEC))) {
2346 ast_log(LOG_WARNING, "Unable to resolve host '%s'\n", host);
2347 return NULL;
2348 }
2349
2350 if (port == 0) {
2351 port = DEFAULT_PORT;
2352 }
2353
2354 for (i = 0; i < num_addrs; ++i) {
2355 struct ast_http_server *server;
2356
2357 /* Use the given port if one was not specified already */
2358 if (!ast_sockaddr_port(&addrs[i])) {
2359 ast_sockaddr_set_port(&addrs[i], port);
2360 }
2361
2362 server = http_server_get_by_addr(name, &addrs[i]);
2363 if (server) {
2364 ast_free(addrs);
2365 return server;
2366 }
2367 }
2368
2369 ast_free(addrs);
2370 return NULL;
2371}
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:2308
@ AST_AF_UNSPEC
Definition netsock2.h:54
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
Definition netsock2.c:280
Socket address structure.
Definition netsock2.h:97

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

Referenced by http_server_get().

◆ http_server_start()

static int http_server_start ( struct ast_http_server server)
static

Definition at line 2242 of file http.c.

2243{
2244 if (server->args.accept_fd != -1) {
2245 /* Already running */
2246 return 0;
2247 }
2248
2249 ast_tcptls_server_start(&server->args);
2250 if (server->args.accept_fd == -1) {
2251 ast_log(LOG_WARNING, "Failed to start HTTP server '%s' at address '%s'\n",
2252 server->name, server->address);
2253 return -1;
2254 }
2255
2256 if (!ao2_link_flags(http_servers, server, OBJ_NOLOCK)) {
2257 ast_log(LOG_WARNING, "Failed to link HTTP server '%s' at address '%s'\n",
2258 server->name, server->address);
2259 return -1;
2260 }
2261
2262 ast_verb(1, "Bound HTTP server '%s' to address %s\n", server->name, server->address);
2263
2264 return 0;
2265}
#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 2050 of file http.c.

2051{
2052 struct ast_tcptls_session_instance *ser = data;
2053 int timeout;
2054 int arg = 1;
2055
2056 if (!ser) {
2057 ao2_cleanup(ser);
2058 return NULL;
2059 }
2060
2062 ast_log(LOG_WARNING, "HTTP session count exceeded %d sessions.\n",
2064 goto done;
2065 }
2066 ast_debug(1, "HTTP opening session. Top level\n");
2067
2068 /*
2069 * Here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
2070 * This is necessary to prevent delays (caused by buffering) as we
2071 * write to the socket in bits and pieces.
2072 */
2073 if (setsockopt(ast_iostream_get_fd(ser->stream), IPPROTO_TCP, TCP_NODELAY, (char *) &arg, sizeof(arg)) < 0) {
2074 ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection: %s\n", strerror(errno));
2075 }
2077
2078 /* Setup HTTP worker private data to keep track of request body reading. */
2082 if (!ser->private_data) {
2083 ast_http_error(ser, 500, "Server Error", "Out of memory");
2084 goto done;
2085 }
2087
2088 /* Determine initial HTTP request wait timeout. */
2089 timeout = session_keep_alive;
2090 if (timeout <= 0) {
2091 /* Persistent connections not enabled. */
2092 timeout = session_inactivity;
2093 }
2094 if (timeout < MIN_INITIAL_REQUEST_TIMEOUT) {
2096 }
2097
2098 /* We can let the stream wait for data to arrive. */
2100
2101 for (;;) {
2102 /* Wait for next potential HTTP request message. */
2104 if (httpd_process_request(ser)) {
2105 /* Break the connection or the connection closed */
2106 break;
2107 }
2108 if (!ser->stream) {
2109 /* Web-socket or similar that took the connection */
2110 break;
2111 }
2112
2113 timeout = session_keep_alive;
2114 if (timeout <= 0) {
2115 /* Persistent connections not enabled. */
2116 break;
2117 }
2118 }
2119
2120done:
2122
2123 ast_debug(1, "HTTP closing session. Top level\n");
2125
2126 ao2_ref(ser, -1);
2127 return NULL;
2128}
@ 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:903
static int session_count
Definition http.c:109
static int httpd_process_request(struct ast_tcptls_session_instance *ser)
Definition http.c:1952
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:764
describes a server instance
Definition tcptls.h:151
int done

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

1953{
1954 RAII_VAR(struct ast_variable *, headers, NULL, ast_variables_destroy);
1955 char *uri;
1956 char *method;
1957 const char *transfer_encoding;
1959 enum ast_http_method http_method = AST_HTTP_UNKNOWN;
1960 int res;
1961 ssize_t len;
1962 char request_line[MAX_HTTP_LINE_LENGTH];
1963
1964 len = ast_iostream_gets(ser->stream, request_line, sizeof(request_line));
1965 if (len <= 0) {
1966 return -1;
1967 }
1968
1969 /* Re-initialize the request body tracking data. */
1970 request = ser->private_data;
1972
1973 if (request_line[len - 1] != '\n') {
1974 /* We didn't get a full line */
1975 ast_http_error(ser, 400, "Bad Request",
1976 (len == sizeof(request_line) - 1) ? "Request line too long" : "Timeout");
1977 return -1;
1978 }
1979
1980 /* Get method */
1981 method = ast_skip_blanks(request_line);
1983 if (*uri) {
1984 *uri++ = '\0';
1985 }
1986
1987 if (!strcasecmp(method,"GET")) {
1988 http_method = AST_HTTP_GET;
1989 } else if (!strcasecmp(method,"POST")) {
1990 http_method = AST_HTTP_POST;
1991 } else if (!strcasecmp(method,"HEAD")) {
1992 http_method = AST_HTTP_HEAD;
1993 } else if (!strcasecmp(method,"PUT")) {
1994 http_method = AST_HTTP_PUT;
1995 } else if (!strcasecmp(method,"DELETE")) {
1996 http_method = AST_HTTP_DELETE;
1997 } else if (!strcasecmp(method,"OPTIONS")) {
1998 http_method = AST_HTTP_OPTIONS;
1999 }
2000
2001 uri = ast_skip_blanks(uri); /* Skip white space */
2002 if (*uri) { /* terminate at the first blank */
2003 char *c = ast_skip_nonblanks(uri);
2004
2005 if (*c) {
2006 *c = '\0';
2007 }
2008 } else {
2009 ast_http_error(ser, 400, "Bad Request", "Invalid Request");
2010 return -1;
2011 }
2012
2013 if (ast_shutdown_final()) {
2014 ast_http_error(ser, 503, "Service Unavailable", "Shutdown in progress");
2015 return -1;
2016 }
2017
2018 /* process "Request Headers" lines */
2019 if (http_request_headers_get(ser, &headers)) {
2020 return -1;
2021 }
2022
2023 transfer_encoding = get_transfer_encoding(headers);
2024 /* Transfer encoding defaults to identity */
2025 if (!transfer_encoding) {
2026 transfer_encoding = "identity";
2027 }
2028
2029 /*
2030 * RFC 2616, section 3.6, we should respond with a 501 for any transfer-
2031 * codings we don't understand.
2032 */
2033 if (strcasecmp(transfer_encoding, "identity") != 0 &&
2034 strcasecmp(transfer_encoding, "chunked") != 0) {
2035 /* Transfer encodings not supported */
2036 ast_http_error(ser, 501, "Unimplemented", "Unsupported Transfer-Encoding.");
2037 return -1;
2038 }
2039
2040 if (http_request_tracking_setup(ser, headers)
2041 || handle_uri(ser, uri, http_method, headers)
2043 res = -1;
2044 } else {
2045 res = 0;
2046 }
2047 return res;
2048}
int ast_shutdown_final(void)
Definition asterisk.c:1884
static int http_request_headers_get(struct ast_tcptls_session_instance *ser, struct ast_variable **headers)
Definition http.c:1870
static int http_request_tracking_setup(struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
Definition http.c:922
static int handle_uri(struct ast_tcptls_session_instance *ser, char *uri, enum ast_http_method method, struct ast_variable *headers)
Definition http.c:1469
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 *attribute_pure 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 412 of file http.c.

416{
417 struct ast_str *out;
418 struct ast_variable *v, *cookies = NULL;
419
421 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
422 return 0;
423 }
424
425 out = ast_str_create(512);
426 if (!out) {
428 ast_http_error(ser, 500, "Server Error", "Out of memory");
429 return 0;
430 }
431
433 "<html><title>Asterisk HTTP Status</title>\r\n"
434 "<body bgcolor=\"#ffffff\">\r\n"
435 "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n"
436 "<h2>&nbsp;&nbsp;Asterisk&trade; HTTP Status</h2></td></tr>\r\n");
437
438 ast_str_append(&out, 0, "<tr><td><i>Server</i></td><td><b>%s</b></td></tr>\r\n", http_server_name);
439 ast_str_append(&out, 0, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix);
440 if (global_http_server) {
441 ast_str_append(&out, 0, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
443 }
444 if (http_tls_cfg.enabled) {
445 ast_str_append(&out, 0, "<tr><td><i>TLS Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
447 }
448 ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
449 for (v = get_vars; v; v = v->next) {
450 ast_str_append(&out, 0, "<tr><td><i>Submitted GET Variable '");
452 ast_str_append(&out, 0, "'</i></td><td>");
454 ast_str_append(&out, 0, "</td></tr>\r\n");
455 }
456 ast_str_append(&out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
457
458 cookies = ast_http_get_cookies(headers);
459 for (v = cookies; v; v = v->next) {
460 ast_str_append(&out, 0, "<tr><td><i>Cookie '");
462 ast_str_append(&out, 0, "'</i></td><td>");
464 ast_str_append(&out, 0, "</td></tr>\r\n");
465 }
466 ast_variables_destroy(cookies);
467
468 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");
469 ast_http_send(ser, method, 200, NULL, NULL, out, 0, 0);
470 return 0;
471}
static void str_append_escaped(struct ast_str **str, const char *in)
Definition http.c:384
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, str_append_escaped(), and ast_variable::value.

◆ load_module()

static int load_module ( void  )
static

Definition at line 2766 of file http.c.

2767{
2769
2771 HTTP_SERVER_BUCKETS, ast_http_server_hash_fn, NULL, ast_http_server_cmp_fn);
2772 if (!http_servers) {
2774 }
2775
2776 if (__ast_http_load(0)) {
2780 }
2781
2783}
@ 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:2477
static struct ast_cli_entry cli_http[]
Definition http.c:2729
#define HTTP_SERVER_BUCKETS
Number of HTTP server buckets.
Definition http.c:2191
@ 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 1567 of file http.c.

1568{
1569 char *parse = ast_strdupa(cookies);
1570 char *cur;
1571 struct ast_variable *vars = NULL, *var;
1572
1573 while ((cur = strsep(&parse, ";"))) {
1574 char *name, *val;
1575
1576 name = val = cur;
1577 strsep(&val, "=");
1578
1580 continue;
1581 }
1582
1583 name = ast_strip(name);
1584 val = ast_strip_quoted(val, "\"", "\"");
1585
1587 continue;
1588 }
1589
1590 ast_debug(1, "HTTP Cookie, Name: '%s' Value: '%s'\n", name, val);
1591
1592 var = ast_variable_new(name, val, __FILE__);
1593 var->next = vars;
1594 vars = var;
1595 }
1596
1597 return vars;
1598}
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:1852
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 2724 of file http.c.

2725{
2726 return __ast_http_load(1);
2727}

References __ast_http_load().

◆ remove_excess_lws()

static void remove_excess_lws ( char *  s)
static

Definition at line 1772 of file http.c.

1773{
1774 char *p, *res = s;
1775 char *buf = ast_malloc(strlen(s) + 1);
1776 char *buf_end;
1777
1778 if (!buf) {
1779 return;
1780 }
1781
1782 buf_end = buf;
1783
1784 while (*s && *(s = ast_skip_blanks(s))) {
1785 p = s;
1786 s = ast_skip_nonblanks(s);
1787
1788 if (buf_end != buf) {
1789 *buf_end++ = ' ';
1790 }
1791
1792 memcpy(buf_end, p, s - p);
1793 buf_end += s - p;
1794 }
1795 *buf_end = '\0';
1796 /* safe since buf will always be less than or equal to res */
1797 strcpy(res, buf);
1798 ast_free(buf);
1799}

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:7999
const char * ast_config_AST_DATA_DIR
Definition options.c:159
#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.

◆ str_append_escaped()

static void str_append_escaped ( struct ast_str **  str,
const char *  in 
)
static

Definition at line 384 of file http.c.

385{
386 const char *cur = in;
387
388 while(*cur) {
389 switch (*cur) {
390 case '<':
391 ast_str_append(str, 0, "&lt;");
392 break;
393 case '>':
394 ast_str_append(str, 0, "&gt;");
395 break;
396 case '&':
397 ast_str_append(str, 0, "&amp;");
398 break;
399 case '"':
400 ast_str_append(str, 0, "&quot;");
401 break;
402 default:
403 ast_str_append(str, 0, "%c", *cur);
404 break;
405 }
406 cur++;
407 }
408
409 return;
410}
const char * str
Definition app_jack.c:150
FILE * in
Definition utils/frame.c:33

References ast_str_append(), in, and str.

Referenced by httpstatus_callback().

◆ 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 = ASTERISK_GPL_KEY , .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 2792 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 2792 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:2669

Definition at line 2729 of file http.c.

2729 {
2730 AST_CLI_DEFINE(handle_show_http, "Display HTTP server status"),
2731};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

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.

131 {
132 .accept_fd = -1,
133 .master = AST_PTHREADT_NULL,
134 .tls_cfg = &http_tls_cfg,
135 .poll_timeout = -1,
136 .name = "https server",
137 .accept_fn = ast_tcptls_server_root,
138 .worker_fn = httpd_helper_thread,
139};

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

◆ [struct]

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_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(), 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 482 of file http.c.

482 {
483 .callback = static_callback,
484 .description = "Asterisk HTTP Static Delivery",
485 .uri = "static",
486 .has_subtree = 1,
487 .data = NULL,
488 .key= __FILE__,
489};
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)
Definition http.c:256

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

473 {
474 .callback = httpstatus_callback,
475 .description = "Asterisk HTTP General Status",
476 .uri = "httpstatus",
477 .has_subtree = 0,
478 .data = NULL,
479 .key = __FILE__,
480};
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)
Definition http.c:412

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

◆ uris

list of supported handlers