[asterisk-commits] rmudgett: branch rmudgett/http_persistent r417736 - in /team/rmudgett/http_pe...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jul 1 18:49:56 CDT 2014


Author: rmudgett
Date: Tue Jul  1 18:49:52 2014
New Revision: 417736

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=417736
Log:
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().

Modified:
    team/rmudgett/http_persistent/include/asterisk/http.h
    team/rmudgett/http_persistent/main/http.c
    team/rmudgett/http_persistent/main/manager.c
    team/rmudgett/http_persistent/res/res_http_post.c
    team/rmudgett/http_persistent/res/res_http_websocket.c

Modified: team/rmudgett/http_persistent/include/asterisk/http.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/http_persistent/include/asterisk/http.h?view=diff&rev=417736&r1=417735&r2=417736
==============================================================================
--- team/rmudgett/http_persistent/include/asterisk/http.h (original)
+++ team/rmudgett/http_persistent/include/asterisk/http.h Tue Jul  1 18:49:52 2014
@@ -69,26 +69,31 @@
 /*!
  * \brief HTTP Callbacks
  *
- * \note The callback function receives server instance, uri, http method,
- * get method (if present in URI), and http headers as arguments and should
- * use the ast_http_send() function for sending content allocated with ast_str
- * and/or content from an opened file descriptor.
+ * \param ser TCP/TLS session object
+ * \param urih Registered URI handler struct for the URI.
+ * \param uri Remaining request URI path (also with the get_params removed).
+ * \param method enum ast_http_method GET, POST, etc.
+ * \param get_params URI argument list passed with the HTTP request.
+ * \param headers HTTP request header-name/value pair list
+ *
+ * \note Should use the ast_http_send() function for sending content
+ * allocated with ast_str and/or content from an opened file descriptor.
  *
  * Status and status text should be sent as arguments to the ast_http_send()
  * function to reflect the status of the request (200 or 304, for example).
  * Content length is calculated by ast_http_send() automatically.
  *
- * Static content may be indicated to the ast_http_send() function, to indicate
- * that it may be cached.
- *
- * \verbatim
- * The return value may include additional headers at the front and MUST
- * include a blank line with \r\n to provide separation between user headers
- * and content (even if no content is specified)
- * \endverbatim
- *
- * For an error response, the ast_http_error() function may be used.
-*/
+ * Static content may be indicated to the ast_http_send() function,
+ * to indicate that it may be cached.
+ *
+ * For a need authentication response, the ast_http_auth() function
+ * should be used.
+ *
+ * For an error response, the ast_http_error() function should be used.
+ *
+ * \retval 0 Continue and process the next HTTP request.
+ * \retval -1 Fatal HTTP connection error.  Force the HTTP connection closed.
+ */
 typedef int (*ast_http_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_params, struct ast_variable *headers);
 
 /*! \brief Definition of a URI handler */
@@ -210,6 +215,18 @@
 void ast_http_prefix(char *buf, int len);
 
 /*!
+ * \brief Request the HTTP connection be closed after this HTTP request.
+ * \since 12.4.0
+ *
+ * \param ser HTTP TCP/TLS session object.
+ *
+ * \note Call before ast_http_error() to make the connection close.
+ *
+ * \return Nothing
+ */
+void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser);
+
+/*!
  * \brief Update the body read success status.
  * \since 12.4.0
  *

Modified: team/rmudgett/http_persistent/main/http.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/http_persistent/main/http.c?view=diff&rev=417736&r1=417735&r2=417736
==============================================================================
--- team/rmudgett/http_persistent/main/http.c (original)
+++ team/rmudgett/http_persistent/main/http.c Tue Jul  1 18:49:52 2014
@@ -77,6 +77,20 @@
 #define MIN_INITIAL_REQUEST_TIMEOUT	10000
 /*! (ms) Idle time between HTTP requests */
 #define DEFAULT_SESSION_KEEP_ALIVE 0
+
+/*! Maximum application/json or application/x-www-form-urlencoded body content length. */
+#if !defined(LOW_MEMORY)
+#define MAX_CONTENT_LENGTH 4096
+#else
+#define MAX_CONTENT_LENGTH 1024
+#endif	/* !defined(LOW_MEMORY) */
+
+/*! Maximum line length for HTTP requests. */
+#if !defined(LOW_MEMORY)
+#define MAX_HTTP_LINE_LENGTH 4096
+#else
+#define MAX_HTTP_LINE_LENGTH 1024
+#endif	/* !defined(LOW_MEMORY) */
 
 /* See http.h for more information about the SSL implementation */
 #if defined(HAVE_OPENSSL) && (defined(HAVE_FUNOPEN) || defined(HAVE_FOPENCOOKIE))
@@ -308,6 +322,7 @@
 
 	http_header = ast_str_create(255);
 	if (!http_header) {
+		ast_http_request_close_on_completion(ser);
 		ast_http_error(ser, 500, "Server Error", "Out of memory");
 		close(fd);
 		return 0;
@@ -334,6 +349,7 @@
 	return 0;
 
 out403:
+	ast_http_request_close_on_completion(ser);
 	ast_http_error(ser, 403, "Access Denied", "You do not have permission to access the requested URL.");
 	return 0;
 }
@@ -353,6 +369,7 @@
 
 	out = ast_str_create(512);
 	if (!out) {
+		ast_http_request_close_on_completion(ser);
 		ast_http_error(ser, 500, "Server Error", "Out of memory");
 		return 0;
 	}
@@ -407,16 +424,21 @@
 	.key= __FILE__,
 };
 
+enum http_private_flags {
+	/*! TRUE if the HTTP request has a body. */
+	HTTP_FLAG_HAS_BODY = (1 << 0),
+	/*! TRUE if the HTTP request body has been read. */
+	HTTP_FLAG_BODY_READ = (1 << 1),
+	/*! TRUE if the HTTP request must close when completed. */
+	HTTP_FLAG_CLOSE_ON_COMPLETION = (1 << 2),
+};
+
 /*! HTTP tcptls worker_fn private data. */
 struct http_worker_private_data {
-	/*! Body length or -1 if chunked.  Valid if has_body is TRUE. */
+	/*! Body length or -1 if chunked.  Valid if HTTP_FLAG_HAS_BODY is TRUE. */
 	int body_length;
-	/*! TRUE if the HTTP request has a body. */
-	unsigned int has_body:1;
-	/*! TRUE if the HTTP request body has been read. */
-	unsigned int body_read:1;
-	/*! TRUE if the HTTP request must close when completed. */
-	unsigned int close_on_completion:1;
+	/*! HTTP body tracking flags */
+	struct ast_flags flags;
 };
 
 void ast_http_send(struct ast_tcptls_session_instance *ser,
@@ -450,11 +472,12 @@
 		struct http_worker_private_data *request;
 
 		request = ser->private_data;
-		if (!request || request->close_on_completion) {
+		if (!request
+			|| ast_test_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION)
+			|| ast_http_body_discard(ser)) {
 			close_connection = 1;
 		} else {
-			ast_http_body_discard(ser);
-			close_connection = request->close_on_completion;
+			close_connection = 0;
 		}
 	}
 
@@ -737,8 +760,8 @@
  * \brief Returns the value of the Transfer-Encoding header.
  *
  * \param headers HTTP headers.
- * \retval Value of the Transfer-Encoding header.
- * \retval 0 if header is not present, or is invalid.
+ * \retval string Value of the Transfer-Encoding header.
+ * \retval NULL if header is not present.
  */
 static const char *get_transfer_encoding(struct ast_variable *headers)
 {
@@ -750,7 +773,9 @@
  *
  * \param s string to decode
  * \param len length of string
- * \return integer value or -1 for decode error
+ *
+ * \retval length on success.
+ * \retval -1 on error.
  */
 static int chunked_atoh(const char *s, int len)
 {
@@ -816,9 +841,34 @@
 	return close_connection;
 }
 
+void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser)
+{
+	struct http_worker_private_data *request = ser->private_data;
+
+	ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
+}
+
+/*!
+ * \internal
+ * \brief Initialize the request tracking information in case of early failure.
+ * \since 12.4.0
+ *
+ * \param request Request tracking information.
+ *
+ * \return Nothing
+ */
+static void http_request_tracking_init(struct http_worker_private_data *request)
+{
+	ast_set_flags_to(&request->flags,
+		HTTP_FLAG_HAS_BODY | HTTP_FLAG_BODY_READ | HTTP_FLAG_CLOSE_ON_COMPLETION,
+		/* Assume close in case request fails early */
+		HTTP_FLAG_CLOSE_ON_COMPLETION);
+}
+
 /*!
  * \internal
  * \brief Setup the HTTP request tracking information.
+ * \since 12.4.0
  *
  * \param ser HTTP TCP/TLS session object.
  * \param headers List of HTTP headers.
@@ -831,23 +881,23 @@
 	struct http_worker_private_data *request = ser->private_data;
 	const char *transfer_encoding;
 
-	request->has_body = 0;
-	request->body_read = 0;
-	request->close_on_completion = http_check_connection_close(headers) ? 1 : 0;
+	ast_set_flags_to(&request->flags,
+		HTTP_FLAG_HAS_BODY | HTTP_FLAG_BODY_READ | HTTP_FLAG_CLOSE_ON_COMPLETION,
+		http_check_connection_close(headers) ? HTTP_FLAG_CLOSE_ON_COMPLETION : 0);
 
 	transfer_encoding = get_transfer_encoding(headers);
 	if (transfer_encoding && !strcasecmp(transfer_encoding, "chunked")) {
 		request->body_length = -1;
-		request->has_body = 1;
+		ast_set_flag(&request->flags, HTTP_FLAG_HAS_BODY);
 		return 0;
 	}
 
 	request->body_length = get_content_length(headers);
 	if (0 < request->body_length) {
-		request->has_body = 1;
+		ast_set_flag(&request->flags, HTTP_FLAG_HAS_BODY);
 	} else if (request->body_length < 0) {
 		/* Invalid Content-Length */
-		request->close_on_completion = 1;
+		ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 		ast_http_error(ser, 400, "Bad Request", "Invalid Content-Length in request!");
 		return -1;
 	}
@@ -859,13 +909,14 @@
 	struct http_worker_private_data *request;
 
 	request = ser->private_data;
-	if (!request->has_body || request->body_read) {
+	if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)
+		|| ast_test_flag(&request->flags, HTTP_FLAG_BODY_READ)) {
 		/* No body to read. */
 		return;
 	}
-	request->body_read = 1;
+	ast_set_flag(&request->flags, HTTP_FLAG_BODY_READ);
 	if (!read_success) {
-		request->close_on_completion = 1;
+		ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 	}
 }
 
@@ -874,14 +925,15 @@
 	struct http_worker_private_data *request;
 	int length;
 	int res;
-	char buf[4096];/* Discard buffer */
+	char buf[MAX_HTTP_LINE_LENGTH];/* Discard buffer */
 
 	request = ser->private_data;
-	if (!request->has_body || request->body_read) {
+	if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)
+		|| ast_test_flag(&request->flags, HTTP_FLAG_BODY_READ)) {
 		/* No body to read or it has already been read. */
 		return 0;
 	}
-	request->body_read = 1;
+	ast_set_flag(&request->flags, HTTP_FLAG_BODY_READ);
 
 	ast_debug(1, "HTTP discarding unused request body\n");
 
@@ -896,7 +948,7 @@
 				ast_log(LOG_WARNING,
 					"Short HTTP request body (Wanted %d of remaining %d)\n",
 					(int) sizeof(buf), length);
-				request->close_on_completion = 1;
+				ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 				return -1;
 			}
 			length -= sizeof(buf);
@@ -906,7 +958,7 @@
 			ast_log(LOG_WARNING,
 				"Short HTTP request body (Wanted %d of remaining %d)\n",
 				length, length);
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			return -1;
 		}
 		return 0;
@@ -918,13 +970,13 @@
 		if (!fgets(buf, sizeof(buf), ser->f)) {
 			ast_log(LOG_WARNING,
 				"Short HTTP read of chunked header\n");
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			return -1;
 		}
 		length = chunked_atoh(buf, sizeof(buf));
 		if (length < 0) {
 			ast_log(LOG_WARNING, "Invalid HTTP chunk size\n");
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			return -1;
 		}
 		if (length == 0) {
@@ -939,7 +991,7 @@
 				ast_log(LOG_WARNING,
 					"Short HTTP request chunk-data (Wanted %d of remaining %d)\n",
 					(int) sizeof(buf), length);
-				request->close_on_completion = 1;
+				ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 				return -1;
 			}
 			length -= sizeof(buf);
@@ -949,7 +1001,7 @@
 			ast_log(LOG_WARNING,
 				"Short HTTP request chunk-data (Wanted %d of remaining %d)\n",
 				length, length);
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			return -1;
 		}
 
@@ -958,14 +1010,14 @@
 		if (res < 1) {
 			ast_log(LOG_WARNING,
 				"Short HTTP chunk sync read (Wanted 2)\n");
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			return -1;
 		}
 		if (buf[0] != 0x0D || buf[1] != 0x0A) {
 			ast_log(LOG_WARNING,
-				"Post HTTP chunk sync bytes wrong (%d, %d)\n",
+				"HTTP chunk sync bytes wrong (%d, %d)\n",
 				buf[0], buf[1]);
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			return -1;
 		}
 	}
@@ -975,7 +1027,7 @@
 		if (!fgets(buf, sizeof(buf), ser->f)) {
 			ast_log(LOG_WARNING,
 				"Short HTTP read of chunked trailer header\n");
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			return -1;
 		}
 
@@ -1005,23 +1057,21 @@
 	int res;
 	int content_length;
 	int chunk_length;
-	char header_line[4096];
+	char header_line[MAX_HTTP_LINE_LENGTH];
 	int bufsize = 250;
 	char *buf;
 
-#define MAX_CONTENT_LENGTH 4096
-
 	request = ser->private_data;
-	if (!request->has_body) {
+	if (!ast_test_flag(&request->flags, HTTP_FLAG_HAS_BODY)) {
 		/* no content - not an error */
 		return NULL;
 	}
-	if (request->body_read) {
+	if (ast_test_flag(&request->flags, HTTP_FLAG_BODY_READ)) {
 		/* Already read the body.  Cannot read again.  Assume no content. */
 		ast_assert(0);
 		return NULL;
 	}
-	request->body_read = 1;
+	ast_set_flag(&request->flags, HTTP_FLAG_BODY_READ);
 
 	ast_debug(2, "HTTP consuming request body\n");
 
@@ -1033,14 +1083,14 @@
 			ast_log(LOG_WARNING,
 				"Excessively long HTTP content. (%d > %d)\n",
 				content_length, MAX_CONTENT_LENGTH);
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			errno = EFBIG;
 			return NULL;
 		}
 		buf = ast_malloc(content_length + 1);
 		if (!buf) {
 			/* Malloc sets ENOMEM */
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			return NULL;
 		}
 
@@ -1051,7 +1101,7 @@
 			 * is good. Treat either one as I/O error */
 			ast_log(LOG_WARNING, "Short HTTP request body (Wanted %d)\n",
 				content_length);
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			errno = EIO;
 			ast_free(buf);
 			return NULL;
@@ -1065,7 +1115,7 @@
 	/* pre-allocate buffer */
 	buf = ast_malloc(bufsize);
 	if (!buf) {
-		request->close_on_completion = 1;
+		ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 		return NULL;
 	}
 
@@ -1076,7 +1126,7 @@
 		if (!fgets(header_line, sizeof(header_line), ser->f)) {
 			ast_log(LOG_WARNING,
 				"Short HTTP read of chunked header\n");
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			errno = EIO;
 			ast_free(buf);
 			return NULL;
@@ -1084,7 +1134,7 @@
 		chunk_length = chunked_atoh(header_line, sizeof(header_line));
 		if (chunk_length < 0) {
 			ast_log(LOG_WARNING, "Invalid HTTP chunk size\n");
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			errno = EIO;
 			ast_free(buf);
 			return NULL;
@@ -1097,7 +1147,7 @@
 			ast_log(LOG_WARNING,
 				"Excessively long HTTP chunk. (%d + %d > %d)\n",
 				content_length, chunk_length, MAX_CONTENT_LENGTH);
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			errno = EFBIG;
 			ast_free(buf);
 			return NULL;
@@ -1114,7 +1164,7 @@
 
 			new_buf = ast_realloc(buf, bufsize);
 			if (!new_buf) {
-				request->close_on_completion = 1;
+				ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 				ast_free(buf);
 				return NULL;
 			}
@@ -1126,7 +1176,7 @@
 		if (res < 1) {
 			ast_log(LOG_WARNING, "Short HTTP chunk read (Wanted %d)\n",
 				chunk_length);
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			errno = EIO;
 			ast_free(buf);
 			return NULL;
@@ -1138,16 +1188,16 @@
 		if (res < 1) {
 			ast_log(LOG_WARNING,
 				"Short HTTP chunk sync read (Wanted 2)\n");
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			errno = EIO;
 			ast_free(buf);
 			return NULL;
 		}
 		if (header_line[0] != 0x0D || header_line[1] != 0x0A) {
 			ast_log(LOG_WARNING,
-				"Post HTTP chunk sync bytes wrong (%d, %d)\n",
+				"HTTP chunk sync bytes wrong (%d, %d)\n",
 				header_line[0], header_line[1]);
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			errno = EIO;
 			ast_free(buf);
 			return NULL;
@@ -1165,7 +1215,7 @@
 		if (!fgets(header_line, sizeof(header_line), ser->f)) {
 			ast_log(LOG_WARNING,
 				"Short HTTP read of chunked trailer header\n");
-			request->close_on_completion = 1;
+			ast_set_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION);
 			errno = EIO;
 			ast_free(buf);
 			return NULL;
@@ -1314,6 +1364,7 @@
 			struct ast_str *http_header = ast_str_create(128);
 
 			if (!http_header) {
+				ast_http_request_close_on_completion(ser);
 				ast_http_error(ser, 500, "Server Error", "Out of memory");
 				break;
 			}
@@ -1564,16 +1615,16 @@
 	enum ast_http_method http_method = AST_HTTP_UNKNOWN;
 	int remaining_headers;
 	int res;
-	char buf[4096];
-	char header_line[4096];
+	char buf[MAX_HTTP_LINE_LENGTH];
+	char header_line[MAX_HTTP_LINE_LENGTH];
 
 	if (!fgets(buf, sizeof(buf), ser->f)) {
 		return -1;
 	}
 
-	/* Initialize the request body flags. */
+	/* Re-initialize the request body tracking data. */
 	request = ser->private_data;
-	request->close_on_completion = 1;/* Assume close in case request fails early */
+	http_request_tracking_init(request);
 
 	/* Get method */
 	method = ast_skip_blanks(buf);
@@ -1683,7 +1734,7 @@
 
 	if (http_request_tracking_setup(ser, headers)
 		|| handle_uri(ser, uri, http_method, headers)
-		|| request->close_on_completion) {
+		|| ast_test_flag(&request->flags, HTTP_FLAG_CLOSE_ON_COMPLETION)) {
 		res = -1;
 	} else {
 		res = 0;
@@ -1741,9 +1792,7 @@
 		ast_http_error(ser, 500, "Server Error", "Out of memory");
 		goto done;
 	}
-
-	/* Assume close in case request fails early */
-	((struct http_worker_private_data *) ser->private_data)->close_on_completion = 1;
+	http_request_tracking_init(ser->private_data);
 
 	/* Determine initial HTTP request wait timeout. */
 	timeout = session_keep_alive;

Modified: team/rmudgett/http_persistent/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/http_persistent/main/manager.c?view=diff&rev=417736&r1=417735&r2=417736
==============================================================================
--- team/rmudgett/http_persistent/main/manager.c (original)
+++ team/rmudgett/http_persistent/main/manager.c Tue Jul  1 18:49:52 2014
@@ -6844,6 +6844,7 @@
 		 * 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 0;
 		}
@@ -6869,6 +6870,7 @@
 	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;
 	}
@@ -6897,6 +6899,7 @@
 				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;
@@ -7077,6 +7080,7 @@
 
 	/* 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 0;
 	}
@@ -7105,6 +7109,7 @@
 	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 0;
 	}
@@ -7155,6 +7160,7 @@
 		 * 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 0;
 		}
@@ -7243,6 +7249,7 @@
 				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;
@@ -7285,6 +7292,7 @@
 	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;

Modified: team/rmudgett/http_persistent/res/res_http_post.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/http_persistent/res/res_http_post.c?view=diff&rev=417736&r1=417735&r2=417736
==============================================================================
--- team/rmudgett/http_persistent/res/res_http_post.c (original)
+++ team/rmudgett/http_persistent/res/res_http_post.c Tue Jul  1 18:49:52 2014
@@ -333,11 +333,13 @@
 
 	ident = ast_http_manid_from_vars(headers);
 	if (!ident || !astman_is_authed(ident)) {
+		ast_http_request_close_on_completion(ser);
 		ast_http_error(ser, 403, "Access Denied", "Sorry, I cannot let you do that, Dave.");
 		return 0;
 	}
 
 	if (!astman_verify_session_writepermissions(ident, EVENT_FLAG_CONFIG)) {
+		ast_http_request_close_on_completion(ser);
 		ast_http_error(ser, 401, "Unauthorized", "You are not authorized to make this request.");
 		return 0;
 	}
@@ -355,6 +357,7 @@
 			if ((sscanf(var->value, "%30u", &content_len)) != 1) {
 				ast_log(LOG_ERROR, "Invalid Content-Length in POST request!\n");
 				fclose(f);
+				ast_http_request_close_on_completion(ser);
 				ast_http_error(ser, 400, "Bad Request", "Invalid Content-Length in POST request!");
 				return 0;
 			}

Modified: team/rmudgett/http_persistent/res/res_http_websocket.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/http_persistent/res/res_http_websocket.c?view=diff&rev=417736&r1=417735&r2=417736
==============================================================================
--- team/rmudgett/http_persistent/res/res_http_websocket.c (original)
+++ team/rmudgett/http_persistent/res/res_http_websocket.c Tue Jul  1 18:49:52 2014
@@ -592,6 +592,7 @@
 	struct ast_str *http_header = ast_str_create(64);
 
 	if (!http_header) {
+		ast_http_request_close_on_completion(ser);
 		ast_http_error(ser, 500, "Server Error", "Out of memory");
 		return;
 	}




More information about the asterisk-commits mailing list