resource_channels.c: Fix memory leak in ast_ari_channels_external_media.

Between ast_ari_channels_external_media(), external_media_rtp_udp(),
and external_media_audiosocket_tcp(), the `variables` structure being passed
around wasn't being cleaned up properly when there was a failure.

* In ast_ari_channels_external_media(), the `variables` structure is now
  defined with RAII_VAR to ensure it always gets cleaned up.

* The ast_variables_destroy() call was removed from external_media_rtp_udp().

* The ast_variables_destroy() call was removed from
  external_media_audiosocket_tcp(), its `endpoint` allocation was changed to
  to use ast_asprintf() as external_media_rtp_udp() does, and it now
  returns an error on failure.

* ast_ari_channels_external_media() now checks the new return code from
  external_media_audiosocket_tcp() and sets the appropriate error response.

Resolves: #1109
(cherry picked from commit 5267c17645)
releases/21
George Joseph 3 months ago committed by Asterisk Development Team
parent 0e8bde6bde
commit 762c0187e1

@ -2111,7 +2111,6 @@ static int external_media_rtp_udp(struct ast_ari_channels_external_media_args *a
NULL, NULL,
args->format, args->format,
response); response);
ast_variables_destroy(variables);
ast_free(endpoint); ast_free(endpoint);
@ -2129,24 +2128,23 @@ static int external_media_rtp_udp(struct ast_ari_channels_external_media_args *a
return 0; return 0;
} }
static void external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args, static int external_media_audiosocket_tcp(struct ast_ari_channels_external_media_args *args,
struct ast_variable *variables, struct ast_variable *variables,
struct ast_ari_response *response) struct ast_ari_response *response)
{ {
size_t endpoint_len;
char *endpoint; char *endpoint;
struct ast_channel *chan; struct ast_channel *chan;
struct varshead *vars; struct varshead *vars;
if (ast_strlen_zero(args->data)) { if (ast_strlen_zero(args->data)) {
ast_ari_response_error(response, 400, "Bad Request", "data can not be empty"); ast_ari_response_error(response, 400, "Bad Request", "data can not be empty");
return; return 1;
} }
endpoint_len = strlen("AudioSocket/") + strlen(args->external_host) + 1 + strlen(args->data) + 1; if (ast_asprintf(&endpoint, "AudioSocket/%s/%s",
endpoint = ast_alloca(endpoint_len); args->external_host, args->data) == -1) {
/* The UUID is stored in the arbitrary data field */ return 1;
snprintf(endpoint, endpoint_len, "AudioSocket/%s/%s", args->external_host, args->data); }
chan = ari_channels_handle_originate_with_id( chan = ari_channels_handle_originate_with_id(
endpoint, endpoint,
@ -2164,10 +2162,11 @@ static void external_media_audiosocket_tcp(struct ast_ari_channels_external_medi
NULL, NULL,
args->format, args->format,
response); response);
ast_variables_destroy(variables);
ast_free(endpoint);
if (!chan) { if (!chan) {
return; return 1;
} }
ast_channel_lock(chan); ast_channel_lock(chan);
@ -2177,6 +2176,7 @@ static void external_media_audiosocket_tcp(struct ast_ari_channels_external_medi
} }
ast_channel_unlock(chan); ast_channel_unlock(chan);
ast_channel_unref(chan); ast_channel_unref(chan);
return 0;
} }
#include "asterisk/config.h" #include "asterisk/config.h"
@ -2185,7 +2185,7 @@ static void external_media_audiosocket_tcp(struct ast_ari_channels_external_medi
void ast_ari_channels_external_media(struct ast_variable *headers, void ast_ari_channels_external_media(struct ast_variable *headers,
struct ast_ari_channels_external_media_args *args, struct ast_ari_response *response) struct ast_ari_channels_external_media_args *args, struct ast_ari_response *response)
{ {
struct ast_variable *variables = NULL; RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
char *external_host; char *external_host;
char *host = NULL; char *host = NULL;
char *port = NULL; char *port = NULL;
@ -2245,7 +2245,11 @@ void ast_ari_channels_external_media(struct ast_variable *headers,
"An internal error prevented this request from being handled"); "An internal error prevented this request from being handled");
} }
} else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) { } else if (strcasecmp(args->encapsulation, "audiosocket") == 0 && strcasecmp(args->transport, "tcp") == 0) {
external_media_audiosocket_tcp(args, variables, response); if (external_media_audiosocket_tcp(args, variables, response)) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"An internal error prevented this request from being handled");
}
} else { } else {
ast_ari_response_error( ast_ari_response_error(
response, 501, "Not Implemented", response, 501, "Not Implemented",

Loading…
Cancel
Save