summaryrefslogtreecommitdiff
path: root/res/res_http_websocket.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 /res/res_http_websocket.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 'res/res_http_websocket.c')
-rw-r--r--res/res_http_websocket.c47
1 files changed, 30 insertions, 17 deletions
diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c
index 90744a1b3..e722980b0 100644
--- a/res/res_http_websocket.c
+++ b/res/res_http_websocket.c
@@ -604,6 +604,19 @@ static char *websocket_combine_key(const char *key, char *res, int res_size)
return res;
}
+static void websocket_bad_request(struct ast_tcptls_session_instance *ser)
+{
+ 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;
+ }
+ ast_str_set(&http_header, 0, "Sec-WebSocket-Version: 7, 8, 13\r\n");
+ ast_http_send(ser, AST_HTTP_UNKNOWN, 400, "Bad Request", http_header, NULL, 0, 0);
+}
+
int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(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)
{
struct ast_variable *v;
@@ -618,7 +631,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
/* Upgrade requests are only permitted on GET methods */
if (method != AST_HTTP_GET) {
ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
- return -1;
+ return 0;
}
server = urih->data;
@@ -648,7 +661,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - did not request WebSocket\n",
ast_sockaddr_stringify(&ser->remote_address));
ast_http_error(ser, 426, "Upgrade Required", NULL);
- return -1;
+ return 0;
} else if (ast_strlen_zero(requested_protocols)) {
/* If there's only a single protocol registered, and the
* client doesn't specify what protocol it's using, go ahead
@@ -658,17 +671,15 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
/* Multiple registered subprotocols; client must specify */
ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - no protocols requested\n",
ast_sockaddr_stringify(&ser->remote_address));
- fputs("HTTP/1.1 400 Bad Request\r\n"
- "Sec-WebSocket-Version: 7, 8, 13\r\n\r\n", ser->f);
- return -1;
+ websocket_bad_request(ser);
+ return 0;
}
} else if (key1 && key2) {
/* Specification defined in http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 and
* http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00 -- not currently supported*/
ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - unsupported version '00/76' chosen\n",
ast_sockaddr_stringify(&ser->remote_address));
- fputs("HTTP/1.1 400 Bad Request\r\n"
- "Sec-WebSocket-Version: 7, 8, 13\r\n\r\n", ser->f);
+ websocket_bad_request(ser);
return 0;
}
@@ -681,8 +692,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
if (!protocol_handler) {
ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - no protocols out of '%s' supported\n",
ast_sockaddr_stringify(&ser->remote_address), protos);
- fputs("HTTP/1.1 400 Bad Request\r\n"
- "Sec-WebSocket-Version: 7, 8, 13\r\n\r\n", ser->f);
+ websocket_bad_request(ser);
return 0;
}
@@ -691,8 +701,13 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
char base64[64];
if (!key || strlen(key) + strlen(WEBSOCKET_GUID) + 1 > 8192) { /* no stack overflows please */
- fputs("HTTP/1.1 400 Bad Request\r\n"
- "Sec-WebSocket-Version: 7, 8, 13\r\n\r\n", ser->f);
+ websocket_bad_request(ser);
+ ao2_ref(protocol_handler, -1);
+ return 0;
+ }
+
+ if (ast_http_body_discard(ser)) {
+ websocket_bad_request(ser);
ao2_ref(protocol_handler, -1);
return 0;
}
@@ -700,8 +715,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
if (!(session = ao2_alloc(sizeof(*session), session_destroy_fn))) {
ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted\n",
ast_sockaddr_stringify(&ser->remote_address));
- fputs("HTTP/1.1 400 Bad Request\r\n"
- "Sec-WebSocket-Version: 7, 8, 13\r\n\r\n", ser->f);
+ websocket_bad_request(ser);
ao2_ref(protocol_handler, -1);
return 0;
}
@@ -735,8 +749,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
/* Specification defined in http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 or completely unknown */
ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - unsupported version '%d' chosen\n",
ast_sockaddr_stringify(&ser->remote_address), version ? version : 75);
- fputs("HTTP/1.1 400 Bad Request\r\n"
- "Sec-WebSocket-Version: 7, 8, 13\r\n\r\n", ser->f);
+ websocket_bad_request(ser);
ao2_ref(protocol_handler, -1);
return 0;
}
@@ -745,8 +758,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
if (setsockopt(ser->fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags))) {
ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - failed to enable keepalive\n",
ast_sockaddr_stringify(&ser->remote_address));
- fputs("HTTP/1.1 400 Bad Request\r\n"
- "Sec-WebSocket-Version: 7, 8, 13\r\n\r\n", ser->f);
+ websocket_bad_request(ser);
ao2_ref(session, -1);
ao2_ref(protocol_handler, -1);
return 0;
@@ -763,6 +775,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
session->secure = ser->ssl ? 1 : 0;
/* Give up ownership of the socket and pass it to the protocol handler */
+ ast_tcptls_stream_set_exclusive_input(ser->stream_cookie, 0);
protocol_handler->callback(session, get_vars, headers);
ao2_ref(protocol_handler, -1);