summaryrefslogtreecommitdiff
path: root/main/manager.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2014-07-03 17:16:55 +0000
committerRichard Mudgett <rmudgett@digium.com>2014-07-03 17:16:55 +0000
commitdbec5e0d8d2d8c51e14f912354d12e1f713b6077 (patch)
tree0d4c189e72b3e0a3a4194efcb62b5779597245d6 /main/manager.c
parent758b13858b79256104c0f81a9adf1924df7d2da9 (diff)
HTTP: Add persistent connection support.
Persistent HTTP connection support is needed due to the increased usage of the Asterisk core HTTP transport and the frequency at which REST API calls are going to be issued. * Add http.conf session_keep_alive option to enable persistent connections. * Parse and discard optional chunked body extension information and trailing request headers. * Increased the maximum application/json and application/x-www-form-urlencoded body size allowed to 4k. The previous 1k was kind of small. * Removed a couple inlined versions of ast_http_manid_from_vars() by calling the function. manager.c:generic_http_callback() and res_http_post.c:http_post_callback() * Add missing va_end() in ast_ari_response_error(). * Eliminated unnecessary RAII_VAR() use in http.c:auth_create(). ASTERISK-23552 #close Reported by: Scott Griepentrog Review: https://reviewboard.asterisk.org/r/3691/ ........ Merged revisions 417880 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@417901 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/manager.c')
-rw-r--r--main/manager.c101
1 files changed, 60 insertions, 41 deletions
diff --git a/main/manager.c b/main/manager.c
index 253517d96..5fcd34716 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -6848,9 +6848,10 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
{
struct mansession s = { .session = NULL, .tcptls_session = ser };
struct mansession_session *session = NULL;
- uint32_t ident = 0;
+ uint32_t ident;
int blastaway = 0;
- struct ast_variable *v, *cookies, *params = get_params;
+ struct ast_variable *v;
+ struct ast_variable *params = get_params;
char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
struct ast_str *http_header = NULL, *out = NULL;
struct message m = { 0 };
@@ -6859,19 +6860,10 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) {
ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
- return -1;
+ return 0;
}
- cookies = ast_http_get_cookies(headers);
- for (v = cookies; v; v = v->next) {
- if (!strcasecmp(v->name, "mansession_id")) {
- sscanf(v->value, "%30x", &ident);
- break;
- }
- }
- if (cookies) {
- ast_variables_destroy(cookies);
- }
+ ident = ast_http_manid_from_vars(headers);
if (!(session = find_session(ident, 1))) {
@@ -6880,18 +6872,21 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
* While it is not in the list we don't need any locking
*/
if (!(session = build_mansession(remote_address))) {
+ ast_http_request_close_on_completion(ser);
ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
- return -1;
+ return 0;
}
ao2_lock(session);
session->send_events = 0;
session->inuse = 1;
- /*!\note There is approximately a 1 in 1.8E19 chance that the following
+ /*!
+ * \note There is approximately a 1 in 1.8E19 chance that the following
* calculation will produce 0, which is an invalid ID, but due to the
* properties of the rand() function (and the constantcy of s), that
* won't happen twice in a row.
*/
- while ((session->managerid = ast_random() ^ (unsigned long) session) == 0);
+ while ((session->managerid = ast_random() ^ (unsigned long) session) == 0) {
+ }
session->last_ev = grab_last();
AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
}
@@ -6903,6 +6898,7 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
ast_mutex_init(&s.lock);
if (http_header == NULL || out == NULL) {
+ ast_http_request_close_on_completion(ser);
ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n");
goto generic_callback_out;
}
@@ -6924,19 +6920,22 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
if (method == AST_HTTP_POST) {
params = ast_http_get_post_vars(ser, headers);
- }
-
- if (!params) {
- switch (errno) {
- case EFBIG:
- ast_http_send(ser, AST_HTTP_POST, 413, "Request Entity Too Large", NULL, NULL, 0, 0);
- break;
- case ENOMEM:
- ast_http_send(ser, AST_HTTP_POST, 500, "Internal Server Error", NULL, NULL, 0, 0);
- break;
- case EIO:
- ast_http_send(ser, AST_HTTP_POST, 400, "Bad Request", NULL, NULL, 0, 0);
- break;
+ if (!params) {
+ switch (errno) {
+ case EFBIG:
+ ast_http_error(ser, 413, "Request Entity Too Large", "Body too large");
+ close_mansession_file(&s);
+ goto generic_callback_out;
+ case ENOMEM:
+ ast_http_request_close_on_completion(ser);
+ ast_http_error(ser, 500, "Server Error", "Out of memory");
+ close_mansession_file(&s);
+ goto generic_callback_out;
+ case EIO:
+ ast_http_error(ser, 400, "Bad Request", "Error parsing request body");
+ close_mansession_file(&s);
+ goto generic_callback_out;
+ }
}
}
@@ -6973,7 +6972,6 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
ast_str_append(&http_header, 0,
"Content-type: text/%s\r\n"
- "Cache-Control: no-cache;\r\n"
"Set-Cookie: mansession_id=\"%08x\"; Version=1; Max-Age=%d\r\n"
"Pragma: SuppressEvents\r\n",
contenttype[format],
@@ -7038,7 +7036,8 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
ao2_unlock(session);
ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0);
- http_header = out = NULL;
+ http_header = NULL;
+ out = NULL;
generic_callback_out:
ast_mutex_destroy(&s.lock);
@@ -7073,7 +7072,7 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
struct ast_variable *v, *params = get_params;
char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
struct ast_str *http_header = NULL, *out = NULL;
- size_t result_size = 512;
+ size_t result_size;
struct message m = { 0 };
unsigned int idx;
size_t hdrlen;
@@ -7093,7 +7092,7 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) {
ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
- return -1;
+ return 0;
}
/* Find "Authorization: " header */
@@ -7109,8 +7108,9 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
/* Digest found - parse */
if (ast_string_field_init(&d, 128)) {
+ ast_http_request_close_on_completion(ser);
ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
- return -1;
+ return 0;
}
if (ast_parse_digest(v->value, &d, 0, 1)) {
@@ -7137,8 +7137,9 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
if (user->acl && !ast_apply_acl(user->acl, remote_address, "Manager User ACL:")) {
AST_RWLIST_UNLOCK(&users);
ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_sockaddr_stringify_addr(&session->addr), d.username);
+ ast_http_request_close_on_completion(ser);
ast_http_error(ser, 403, "Permission denied", "Permission denied\n");
- return -1;
+ return 0;
}
/* --- We have auth, so check it */
@@ -7187,8 +7188,9 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
* While it is not in the list we don't need any locking
*/
if (!(session = build_mansession(remote_address))) {
+ ast_http_request_close_on_completion(ser);
ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
- return -1;
+ return 0;
}
ao2_lock(session);
@@ -7268,6 +7270,23 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
if (method == AST_HTTP_POST) {
params = ast_http_get_post_vars(ser, headers);
+ if (!params) {
+ switch (errno) {
+ case EFBIG:
+ ast_http_error(ser, 413, "Request Entity Too Large", "Body too large");
+ close_mansession_file(&s);
+ goto auth_callback_out;
+ case ENOMEM:
+ ast_http_request_close_on_completion(ser);
+ ast_http_error(ser, 500, "Server Error", "Out of memory");
+ close_mansession_file(&s);
+ goto auth_callback_out;
+ case EIO:
+ ast_http_error(ser, 400, "Bad Request", "Error parsing request body");
+ close_mansession_file(&s);
+ goto auth_callback_out;
+ }
+ }
}
for (v = params; v && m.hdrcount < ARRAY_LEN(m.headers); v = v->next) {
@@ -7296,15 +7315,14 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
m.headers[idx] = NULL;
}
- if (s.f) {
- result_size = ftell(s.f); /* Calculate approx. size of result */
- }
+ result_size = ftell(s.f); /* Calculate approx. size of result */
http_header = ast_str_create(80);
out = ast_str_create(result_size * 2 + 512);
-
if (http_header == NULL || out == NULL) {
+ ast_http_request_close_on_completion(ser);
ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n");
+ close_mansession_file(&s);
goto auth_callback_out;
}
@@ -7334,7 +7352,8 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
}
ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0);
- http_header = out = NULL;
+ http_header = NULL;
+ out = NULL;
auth_callback_out:
ast_mutex_destroy(&s.lock);