mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
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/ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/12@417880 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -587,6 +587,19 @@ static struct websocket_protocol *one_protocol(
|
||||
return ao2_callback(server->protocols, OBJ_NOLOCK, NULL, NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -601,7 +614,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;
|
||||
@@ -631,7 +644,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
|
||||
@@ -641,17 +654,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;
|
||||
}
|
||||
|
||||
@@ -664,8 +675,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;
|
||||
}
|
||||
|
||||
@@ -680,8 +690,13 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
|
||||
|
||||
combined_length = (key ? strlen(key) : 0) + strlen(WEBSOCKET_GUID) + 1;
|
||||
if (!key || combined_length > 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;
|
||||
}
|
||||
@@ -689,8 +704,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;
|
||||
}
|
||||
@@ -729,8 +743,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;
|
||||
}
|
||||
@@ -739,8 +752,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;
|
||||
@@ -757,6 +769,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);
|
||||
|
||||
|
Reference in New Issue
Block a user