Asterisk - The Open Source Telephony Project  21.4.1
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"

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. More...
 
void ast_http_auth (struct ast_tcptls_session_instance *ser, const char *realm, const unsigned long nonce, const unsigned long opaque, int stale, const char *text)
 Send http "401 Unauthorized" response and close socket.
 
int ast_http_body_discard (struct ast_tcptls_session_instance *ser)
 Read and discard any unread HTTP request body. More...
 
void ast_http_body_read_status (struct ast_tcptls_session_instance *ser, int read_success)
 Update the body read success status. More...
 
void ast_http_create_response (struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, struct ast_str *http_header_data, const char *text)
 Creates and sends a formatted http response message. More...
 
void ast_http_error (struct ast_tcptls_session_instance *ser, int status_code, const char *status_title, const char *text)
 Send HTTP error message and close socket.
 
const char * ast_http_ftype2mtype (const char *ftype)
 Return mime type based on extension. More...
 
struct ast_http_authast_http_get_auth (struct ast_variable *headers)
 Get HTTP authentication information from headers. More...
 
static char * ast_http_get_contents (int *return_length, struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
 Returns the contents (body) of the HTTP request. More...
 
struct ast_variableast_http_get_cookies (struct ast_variable *headers)
 Get cookie from Request headers.
 
struct ast_jsonast_http_get_json (struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
 Get JSON from client Request Entity-Body, if content type is application/json. More...
 
struct ast_variableast_http_get_post_vars (struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
 Get post variables from client Request Entity-Body, if content type is application/x-www-form-urlencoded. More...
 
int ast_http_header_match (const char *name, const char *expected_name, const char *value, const char *expected_value)
 Check if the header and value match (case insensitive) their associated expected values. More...
 
int ast_http_header_match_in (const char *name, const char *expected_name, const char *value, const char *expected_value)
 Check if the header name matches the expected header name. If so, then check to see if the value can be located in the expected value. More...
 
int ast_http_header_parse (char *buf, char **name, char **value)
 Parse a header into the given name/value strings. More...
 
uint32_t ast_http_manid_from_vars (struct ast_variable *headers)
 Return manager id, if exist, from request headers. More...
 
void ast_http_prefix (char *buf, int len)
 Return the current prefix. More...
 
void ast_http_request_close_on_completion (struct ast_tcptls_session_instance *ser)
 Request the HTTP connection be closed after this HTTP request. More...
 
int ast_http_response_status_line (const char *buf, const char *version, int code)
 Parse the http response status line. More...
 
void ast_http_send (struct ast_tcptls_session_instance *ser, enum ast_http_method method, int status_code, const char *status_title, struct ast_str *http_header, struct ast_str *out, int fd, unsigned int static_content)
 Generic function for sending HTTP/1.1 response. More...
 
int ast_http_uri_link (struct ast_http_uri *urih)
 Link the new uri into the list. More...
 
void ast_http_uri_unlink (struct ast_http_uri *urih)
 Unregister a URI handler.
 
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. More...
 
static char * get_content_type (struct ast_variable *headers)
 Retrieves the content type specified in the "Content-Type" header. More...
 
static const char * get_header (struct ast_variable *headers, const char *field_name)
 Retrieves the header with the given field name. More...
 
static const char * get_transfer_encoding (struct ast_variable *headers)
 Returns the value of the Transfer-Encoding header. More...
 
static char * handle_show_http (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int handle_uri (struct ast_tcptls_session_instance *ser, char *uri, enum ast_http_method method, struct ast_variable *headers)
 
static int http_body_check_chunk_sync (struct ast_tcptls_session_instance *ser)
 
static int http_body_discard_chunk_trailer_headers (struct ast_tcptls_session_instance *ser)
 
static int http_body_discard_contents (struct ast_tcptls_session_instance *ser, int length, const char *what_getting)
 
static int http_body_get_chunk_length (struct ast_tcptls_session_instance *ser)
 
static int http_body_read_contents (struct ast_tcptls_session_instance *ser, char *buf, int length, const char *what_getting)
 
static int http_check_connection_close (struct ast_variable *headers)
 
static int http_request_headers_get (struct ast_tcptls_session_instance *ser, struct ast_variable **headers)
 
static void http_request_tracking_init (struct http_worker_private_data *request)
 
static int http_request_tracking_setup (struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
 
static struct ast_http_serverhttp_server_create (const char *name, const char *address, const struct ast_sockaddr *addr)
 
static void http_server_destroy (void *obj)
 
static void http_server_discard (struct ast_http_server *server)
 Discard/Drop a HTTP server. More...
 
static struct ast_http_serverhttp_server_get (const char *name, const char *host, uint32_t port, struct ast_http_server **replace_me)
 Retrieve, or create and start a HTTP server. More...
 
static struct ast_http_serverhttp_server_get_by_addr (const char *name, const struct ast_sockaddr *addr)
 Retrieve, or create a HTTP server object by sock address. More...
 
static struct ast_http_serverhttp_server_get_by_host (const char *name, const char *host, uint32_t port)
 Retrieve, or create a HTTP server object by host. More...
 
static int http_server_start (struct ast_http_server *server)
 
static void * httpd_helper_thread (void *arg)
 
static int httpd_process_request (struct ast_tcptls_session_instance *ser)
 
static int httpstatus_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
 
static int load_module (void)
 
static struct ast_variableparse_cookies (const char *cookies)
 
static int reload_module (void)
 
static void remove_excess_lws (char *s)
 
static int static_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Built-in HTTP Server" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "da6642af068ee5e6490c5b1d2cc1d238" , .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 = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct uris uris = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 

Detailed Description

http server for AMI access

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

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

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

AMI over HTTP support - AMI over the http protocol

Definition in file http.c.

Macro Definition Documentation

#define BASIC_LEN   6

strlen(BASIC_PREFIX)

Definition at line 1580 of file http.c.

Referenced by ast_http_get_auth().

#define DEFAULT_RESPONSE_HEADER_LENGTH   512

Max size for the http response header

Definition at line 81 of file http.c.

Referenced by ast_http_auth(), and ast_http_error().

#define DEFAULT_SESSION_INACTIVITY   30000

(ms) Idle time waiting for data.

Definition at line 73 of file http.c.

#define DEFAULT_SESSION_KEEP_ALIVE   15000

(ms) Idle time between HTTP requests

Definition at line 77 of file http.c.

#define INITIAL_RESPONSE_BODY_BUFFER   1024

Initial response body length.

Definition at line 92 of file http.c.

Referenced by ast_http_create_response().

#define MAX_CONTENT_LENGTH   40960

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

Definition at line 85 of file http.c.

Referenced by ast_http_get_contents().

#define MAX_HTTP_LINE_LENGTH   4096

Maximum line length for HTTP requests.

Definition at line 99 of file http.c.

#define MAX_HTTP_REQUEST_HEADERS   100

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

Definition at line 1747 of file http.c.

#define MAX_SERVER_NAME_LENGTH   128

Max size for the http server name

Definition at line 79 of file http.c.

Referenced by ast_http_create_response(), and ast_http_send().

#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

Enumerator
HTTP_FLAG_HAS_BODY 

TRUE if the HTTP request has a body.

HTTP_FLAG_BODY_READ 

TRUE if the HTTP request body has been read.

HTTP_FLAG_CLOSE_ON_COMPLETION 

TRUE if the HTTP request must close when completed.

Definition at line 442 of file http.c.

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

Function Documentation

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.

Referenced by handle_options().

194 {
195  int x;
196 
197  for (x = 0; x < ARRAY_LEN(ast_http_methods_text); x++) {
198  if (ast_http_methods_text[x].method == method) {
199  return ast_http_methods_text[x].text;
200  }
201  }
202 
203  return NULL;
204 }
int ast_http_body_discard ( struct ast_tcptls_session_instance ser)

Read and discard any unread HTTP request body.

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

Definition at line 1122 of file http.c.

References ast_debug, http_worker_private_data::body_length, http_worker_private_data::flags, HTTP_FLAG_BODY_READ, HTTP_FLAG_CLOSE_ON_COMPLETION, HTTP_FLAG_HAS_BODY, and ast_tcptls_session_instance::private_data.

Referenced by ast_http_send().

1123 {
1124  struct http_worker_private_data *request;
1125 
1126  request = ser->private_data;
1127  if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)
1128  || ast_test_flag(&request->flags, HTTP_FLAG_BODY_READ)) {
1129  /* No body to read or it has already been read. */
1130  return 0;
1131  }
1132  ast_set_flag(&request->flags, HTTP_FLAG_BODY_READ);
1133 
1134  ast_debug(1, "HTTP discarding unused request body\n");
1135 
1136  ast_assert(request->body_length != 0);
1137  if (0 < request->body_length) {
1138  if (http_body_discard_contents(ser, request->body_length, "body")) {
1139  ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
1140  return -1;
1141  }
1142  return 0;
1143  }
1144 
1145  /* parse chunked-body */
1146  for (;;) {
1147  int length;
1148 
1149  length = http_body_get_chunk_length(ser);
1150  if (length < 0) {
1151  ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
1152  return -1;
1153  }
1154  if (length == 0) {
1155  /* parsed last-chunk */
1156  break;
1157  }
1158 
1159  if (http_body_discard_contents(ser, length, "chunk-data")
1160  || http_body_check_chunk_sync(ser)) {
1161  ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
1162  return -1;
1163  }
1164  }
1165 
1166  /* Read and discard any trailer entity-header lines. */
1167  if (http_body_discard_chunk_trailer_headers(ser)) {
1168  ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
1169  return -1;
1170  }
1171  return 0;
1172 }
#define ast_debug(level,...)
Log a DEBUG message.
struct ast_flags flags
Definition: http.c:456
void ast_http_body_read_status ( struct ast_tcptls_session_instance ser,
int  read_success 
)

Update the body read success status.

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

Definition at line 901 of file http.c.

References http_worker_private_data::flags, HTTP_FLAG_BODY_READ, HTTP_FLAG_CLOSE_ON_COMPLETION, HTTP_FLAG_HAS_BODY, and ast_tcptls_session_instance::private_data.

902 {
903  struct http_worker_private_data *request;
904 
905  request = ser->private_data;
906  if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)
907  || ast_test_flag(&request->flags, HTTP_FLAG_BODY_READ)) {
908  /* No body to read. */
909  return;
910  }
911  ast_set_flag(&request->flags, HTTP_FLAG_BODY_READ);
912  if (!read_success) {
913  ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
914  }
915 }
struct ast_flags flags
Definition: http.c:456
void ast_http_create_response ( struct ast_tcptls_session_instance ser,
int  status_code,
const char *  status_title,
struct ast_str http_header_data,
const char *  text 
)

Creates and sends a formatted http response message.

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

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

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

Since
13.2.0

Definition at line 570 of file http.c.

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

Referenced by ast_http_auth(), and ast_http_error().

572 {
573  char server_name[MAX_SERVER_NAME_LENGTH];
574  struct ast_str *server_address = ast_str_create(MAX_SERVER_NAME_LENGTH);
576 
577  if (!http_header_data || !server_address || !out) {
578  ast_free(http_header_data);
579  ast_free(server_address);
580  ast_free(out);
581  if (ser) {
582  ast_debug(1, "HTTP closing session. OOM.\n");
584  }
585  return;
586  }
587 
588  if(!ast_strlen_zero(http_server_name)) {
589  ast_xml_escape(http_server_name, server_name, sizeof(server_name));
590  ast_str_set(&server_address,
591  0,
592  "<address>%s</address>\r\n",
593  server_name);
594  }
595 
596  ast_str_set(&out,
597  0,
598  "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
599  "<html><head>\r\n"
600  "<title>%d %s</title>\r\n"
601  "</head><body>\r\n"
602  "<h1>%s</h1>\r\n"
603  "<p>%s</p>\r\n"
604  "<hr />\r\n"
605  "%s"
606  "</body></html>\r\n",
607  status_code,
608  status_title,
609  status_title,
610  text ? text : "",
611  ast_str_buffer(server_address));
612 
613  ast_free(server_address);
614 
615  ast_http_send(ser,
617  status_code,
618  status_title,
619  http_header_data,
620  out,
621  0,
622  0);
623 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define INITIAL_RESPONSE_BODY_BUFFER
Definition: http.c:92
int ast_xml_escape(const char *string, char *outbuf, size_t buflen)
Escape reserved characters for use in XML.
Definition: utils.c:864
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
#define MAX_SERVER_NAME_LENGTH
Definition: http.c:79
#define ast_debug(level,...)
Log a DEBUG message.
Support for dynamic strings.
Definition: strings.h:623
void ast_http_send(struct ast_tcptls_session_instance *ser, enum ast_http_method method, int status_code, const char *status_title, struct ast_str *http_header, struct ast_str *out, int fd, unsigned int static_content)
Generic function for sending HTTP/1.1 response.
Definition: http.c:459
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:915
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
const char* ast_http_ftype2mtype ( const char *  ftype)

Return mime type based on extension.

Parameters
ftypefilename extension
Returns
String containing associated MIME type
Since
1.8

Definition at line 206 of file http.c.

References mimetypes.

Referenced by build_profile().

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

Get HTTP authentication information from headers.

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

Parameters
headersHTTP request headers.
Returns
HTTP auth structure.
Return values
NULLif no supported HTTP auth headers present.
Since
12

Definition at line 1582 of file http.c.

References ast_base64decode(), ast_begins_with(), BASIC_LEN, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by authenticate_user().

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

Returns the contents (body) of the HTTP request.

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

Definition at line 1184 of file http.c.

References ast_debug, ast_malloc, ast_realloc, http_worker_private_data::body_length, http_worker_private_data::flags, HTTP_FLAG_BODY_READ, HTTP_FLAG_CLOSE_ON_COMPLETION, HTTP_FLAG_HAS_BODY, MAX_CONTENT_LENGTH, and ast_tcptls_session_instance::private_data.

Referenced by ast_http_get_json(), and ast_http_get_post_vars().

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

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

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

Definition at line 1317 of file http.c.

References ast_http_get_contents(), ast_json_load_buf(), get_content_type(), and RAII_VAR.

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

Get post variables from client Request Entity-Body, if content type is application/x-www-form-urlencoded.

Parameters
serTCP/TLS session object
headersList of HTTP headers
Returns
List of variables within the POST body
Note
Since returned list is malloc'd, list should be free'd by the calling function
Since
1.8

Definition at line 1356 of file http.c.

References ast_http_get_contents(), ast_uri_decode(), get_content_type(), and RAII_VAR.

Referenced by generic_http_callback().

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

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

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

Definition at line 1713 of file http.c.

1715 {
1716  if (strcasecmp(name, expected_name)) {
1717  /* no value to validate if names don't match */
1718  return 0;
1719  }
1720 
1721  if (strcasecmp(value, expected_value)) {
1722  ast_log(LOG_ERROR, "Invalid header value - expected %s "
1723  "received %s", value, expected_value);
1724  return -1;
1725  }
1726  return 1;
1727 }
int ast_http_header_match_in ( const char *  name,
const char *  expected_name,
const char *  value,
const char *  expected_value 
)

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

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

Definition at line 1729 of file http.c.

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

Parse a header into the given name/value strings.

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

Definition at line 1691 of file http.c.

References ast_skip_blanks(), and ast_trim_blanks().

1692 {
1693  ast_trim_blanks(buf);
1694  if (ast_strlen_zero(buf)) {
1695  return -1;
1696  }
1697 
1698  *value = buf;
1699  *name = strsep(value, ":");
1700  if (!*value) {
1701  return 1;
1702  }
1703 
1705  if (ast_strlen_zero(*value) || ast_strlen_zero(*name)) {
1706  return 1;
1707  }
1708 
1709  remove_excess_lws(*value);
1710  return 0;
1711 }
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:186
uint32_t ast_http_manid_from_vars ( struct ast_variable headers)

Return manager id, if exist, from request headers.

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

Definition at line 220 of file http.c.

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

Referenced by generic_http_callback().

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

Return the current prefix.

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

Definition at line 236 of file http.c.

References ast_copy_string().

237 {
238  if (buf) {
239  ast_copy_string(buf, prefix, len);
240  }
241 }
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
void ast_http_request_close_on_completion ( struct ast_tcptls_session_instance ser)

Request the HTTP connection be closed after this HTTP request.

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

Definition at line 840 of file http.c.

References http_worker_private_data::flags, HTTP_FLAG_CLOSE_ON_COMPLETION, and ast_tcptls_session_instance::private_data.

Referenced by generic_http_callback().

841 {
842  struct http_worker_private_data *request = ser->private_data;
843 
844  ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
845 }
struct ast_flags flags
Definition: http.c:456
int ast_http_response_status_line ( const char *  buf,
const char *  version,
int  code 
)

Parse the http response status line.

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

Definition at line 1639 of file http.c.

1640 {
1641  int status_code;
1642  size_t size = strlen(version);
1643 
1644  if (strncmp(buf, version, size) || buf[size] != ' ') {
1645  ast_log(LOG_ERROR, "HTTP version not supported - "
1646  "expected %s\n", version);
1647  return -1;
1648  }
1649 
1650  /* skip to status code (version + space) */
1651  buf += size + 1;
1652 
1653  if (sscanf(buf, "%d", &status_code) != 1) {
1654  ast_log(LOG_ERROR, "Could not read HTTP status code - "
1655  "%s\n", buf);
1656  return -1;
1657  }
1658 
1659  return status_code;
1660 }
void ast_http_send ( struct ast_tcptls_session_instance ser,
enum ast_http_method  method,
int  status_code,
const char *  status_title,
struct ast_str http_header,
struct ast_str out,
int  fd,
unsigned int  static_content 
)

Generic function for sending HTTP/1.1 response.

Parameters
serTCP/TLS session object
methodGET/POST/HEAD
status_codeHTTP response code (200/401/403/404/500)
status_titleEnglish equivalent to the status_code parameter
http_headerAn ast_str object containing all headers
outAn ast_str object containing the body of the response
fdIf out is NULL, a file descriptor where the body of the response is held (otherwise -1)
static_contentZero if the content is dynamically generated and should not be cached; nonzero otherwise
Note
Function determines the HTTP response header from status_code, status_header, and http_header.

Extra HTTP headers MUST be present only in the http_header argument. The argument "out" should contain only content of the response (no headers!).

HTTP content can be constructed from the argument "out", if it is not NULL; otherwise, the function will read content from FD.

This function calculates the content-length http header itself.

Both the http_header and out arguments will be freed by this function; however, if FD is open, it will remain open.

Since
1.8

Definition at line 459 of file http.c.

References ast_debug, ast_http_body_discard(), ast_iostream_printf(), ast_iostream_write(), ast_localtime(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_str_strlen(), ast_strftime(), ast_tcptls_close_session_file(), ast_tvnow(), http_worker_private_data::flags, HTTP_FLAG_CLOSE_ON_COMPLETION, MAX_SERVER_NAME_LENGTH, ast_tcptls_session_instance::private_data, and ast_tcptls_session_instance::stream.

Referenced by ast_http_create_response(), and generic_http_callback().

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

Link the new uri into the list.

Register a URI handler.

They are sorted by length of the string, not alphabetically. Duplicate entries are not replaced, but the insertion order (using <= and not just <) makes sure that more recent insertions hide older ones. On a lookup, we just scan the list and stop at the first matching entry.

Definition at line 676 of file http.c.

References AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module().

677 {
678  struct ast_http_uri *uri;
679  int len = strlen(urih->uri);
680 
682 
683  urih->prefix = prefix;
684 
685  if ( AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len ) {
686  AST_RWLIST_INSERT_HEAD(&uris, urih, entry);
688  return 0;
689  }
690 
691  AST_RWLIST_TRAVERSE(&uris, uri, entry) {
692  if (AST_RWLIST_NEXT(uri, entry) &&
693  strlen(AST_RWLIST_NEXT(uri, entry)->uri) <= len) {
694  AST_RWLIST_INSERT_AFTER(&uris, uri, urih, entry);
696 
697  return 0;
698  }
699  }
700 
701  AST_RWLIST_INSERT_TAIL(&uris, urih, entry);
702 
704 
705  return 0;
706 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
Definition of a URI handler.
Definition: http.h:102
Definition: search.h:40
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
Definition: http.c:141
static int get_content_length ( struct ast_variable headers)
static

Returns the value of the Content-Length header.

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

Definition at line 790 of file http.c.

References get_header().

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

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

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

Note
the return value is an allocated string that needs to be freed.
Returns
the content type/subtype
Return values
NULLif the header is not found.

Definition at line 765 of file http.c.

References ast_strndup, and get_header().

Referenced by ast_http_get_json(), and ast_http_get_post_vars().

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

Retrieves the header with the given field name.

Parameters
headersHeaders to search.
field_nameName of the header to find.
Returns
Associated header value.
Return values
NULLif header is not present.

Definition at line 742 of file http.c.

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

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

743 {
744  struct ast_variable *v;
745 
746  for (v = headers; v; v = v->next) {
747  if (!strcasecmp(v->name, field_name)) {
748  return v->value;
749  }
750  }
751  return NULL;
752 }
struct ast_variable * next
Structure for variables, used for configurations and for channel variables.
static const char* get_transfer_encoding ( struct ast_variable headers)
static

Returns the value of the Transfer-Encoding header.

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

Definition at line 815 of file http.c.

References get_header().

816 {
817  return get_header(headers, "Transfer-Encoding");
818 }
static const char * get_header(struct ast_variable *headers, const char *field_name)
Retrieves the header with the given field name.
Definition: http.c:742
static void http_server_discard ( struct ast_http_server server)
static

Discard/Drop a HTTP server.

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

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

Note
NULL tolerant
Parameters
serverThe server object

Definition at line 2170 of file http.c.

References ao2_ref, and ao2_unlink.

Referenced by http_server_get().

2171 {
2172  if (!server) {
2173  return;
2174  }
2175 
2176  /*
2177  * If only two references were on the object then the last one is from
2178  * the servers container, so remove from container now.
2179  */
2180  if (ao2_ref(server, -1) == 2) {
2181  ao2_unlink(http_servers, server);
2182  }
2183 }
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
static struct ast_http_server* http_server_get ( const char *  name,
const char *  host,
uint32_t  port,
struct ast_http_server **  replace_me 
)
static

Retrieve, or create and start a HTTP server.

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

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

Definition at line 2280 of file http.c.

References ao2_ref, http_server_discard(), and http_server_get_by_host().

2282 {
2283  struct ast_http_server *server;
2284 
2285  ao2_lock(http_servers);
2286 
2287  server = http_server_get_by_host(name, host, port);
2288 
2289  if (replace_me) {
2290  /* Only replace if different */
2291  if (*replace_me == server) {
2292  ao2_cleanup(server);
2293  ao2_unlock(http_servers);
2294  return *replace_me;
2295  }
2296 
2297  if (*replace_me) {
2298  http_server_discard(*replace_me);
2299  }
2300 
2301  *replace_me = server;
2302  }
2303 
2304  if (server && http_server_start(server)) {
2305  if (replace_me) {
2306  *replace_me = NULL;
2307  }
2308 
2309  ao2_ref(server, -1);
2310  server = NULL;
2311  }
2312 
2313  ao2_unlock(http_servers);
2314  return server;
2315 }
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
static void http_server_discard(struct ast_http_server *server)
Discard/Drop a HTTP server.
Definition: http.c:2170
static struct ast_http_server * http_server_get_by_host(const char *name, const char *host, uint32_t port)
Retrieve, or create a HTTP server object by host.
Definition: http.c:2228
static struct ast_http_server* http_server_get_by_addr ( const char *  name,
const struct ast_sockaddr addr 
)
static

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

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

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

Definition at line 2198 of file http.c.

References address, ast_sockaddr_stringify(), OBJ_KEY, and OBJ_NOLOCK.

Referenced by http_server_get_by_host().

2200 {
2201  struct ast_http_server *server;
2202  const char *address;
2203 
2204  address = ast_sockaddr_stringify(addr);
2205  if (ast_strlen_zero(address)) {
2206  return NULL;
2207  }
2208 
2209  server = ao2_find(http_servers, address, OBJ_KEY | OBJ_NOLOCK);
2210 
2211  return server ?: http_server_create(name, address, addr);
2212 }
#define OBJ_KEY
Definition: astobj2.h:1151
static struct ast_sockaddr address
Address for UDPTL.
Definition: res_pjsip_t38.c:56
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
static struct ast_http_server* http_server_get_by_host ( const char *  name,
const char *  host,
uint32_t  port 
)
static

Retrieve, or create a HTTP server object by host.

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

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

Definition at line 2228 of file http.c.

References ast_sockaddr_port, ast_sockaddr_resolve(), ast_sockaddr_set_port, and http_server_get_by_addr().

Referenced by http_server_get().

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

Variable Documentation

struct ast_cli_entry cli_http[]
static
Initial value:
= {
{ .handler = handle_show_http , .summary = "Display HTTP server status" ,},
}

Definition at line 2619 of file http.c.

struct ast_http_server* global_http_server = NULL

The default configured HTTP server

Definition at line 129 of file http.c.

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

list of supported handlers