summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
Diffstat (limited to 'res')
-rw-r--r--res/ari/resource_events.c4
-rw-r--r--res/res_pjproject.c2
-rw-r--r--res/res_pjsip/location.c5
-rw-r--r--res/res_pjsip/pjsip_configuration.c2
-rw-r--r--res/res_pjsip_config_wizard.c16
-rw-r--r--res/res_pjsip_exten_state.c7
-rw-r--r--res/res_pjsip_history.c30
-rw-r--r--res/res_pjsip_outbound_registration.c6
-rw-r--r--res/res_pjsip_pubsub.c28
-rw-r--r--res/res_pjsip_session.c119
-rw-r--r--res/res_pjsip_t38.c13
-rw-r--r--res/res_stasis_playback.c6
-rw-r--r--res/stasis/app.c9
-rw-r--r--res/stasis/messaging.c12
14 files changed, 184 insertions, 75 deletions
diff --git a/res/ari/resource_events.c b/res/ari/resource_events.c
index 4be5d0223..992c562a7 100644
--- a/res/ari/resource_events.c
+++ b/res/ari/resource_events.c
@@ -108,7 +108,9 @@ static void stasis_app_message_handler(
msg_application);
} else if (!session->ws_session) {
/* If the websocket is NULL, the message goes to the queue */
- AST_VECTOR_APPEND(&session->message_queue, message);
+ if (!AST_VECTOR_APPEND(&session->message_queue, message)) {
+ ast_json_ref(message);
+ }
ast_log(LOG_WARNING,
"Queued '%s' message for Stasis app '%s'; websocket is not ready\n",
msg_type,
diff --git a/res/res_pjproject.c b/res/res_pjproject.c
index 86b2502e5..6137898a3 100644
--- a/res/res_pjproject.c
+++ b/res/res_pjproject.c
@@ -234,7 +234,7 @@ static void capture_buildopts_cb(int level, const char *data, int len)
}
dup = ast_strdup(ast_skip_blanks(data));
- if (AST_VECTOR_ADD_SORTED(&buildopts, dup, strcmp)) {
+ if (dup && AST_VECTOR_ADD_SORTED(&buildopts, dup, strcmp)) {
ast_free(dup);
}
}
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c
index 9945c7c10..0d7b3da31 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -1219,6 +1219,11 @@ static int contact_apply_handler(const struct ast_sorcery *sorcery, void *object
struct ast_sip_contact_status *status;
struct ast_sip_contact *contact = object;
+ if (ast_strlen_zero(contact->uri)) {
+ ast_log(LOG_ERROR, "A URI on dynamic contact '%s' is empty\n",
+ ast_sorcery_object_get_id(contact));
+ return -1;
+ }
status = ast_res_pjsip_find_or_create_contact_status(contact);
ao2_cleanup(status);
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index a6afe5e53..168d86989 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -508,6 +508,8 @@ int ast_sip_auth_vector_init(struct ast_sip_auth_vector *auths, const char *valu
goto failure;
}
if (AST_VECTOR_APPEND(auths, val)) {
+ ast_free(val);
+
goto failure;
}
}
diff --git a/res/res_pjsip_config_wizard.c b/res/res_pjsip_config_wizard.c
index 1526dc2e2..3a761a7c7 100644
--- a/res/res_pjsip_config_wizard.c
+++ b/res/res_pjsip_config_wizard.c
@@ -1001,7 +1001,10 @@ static int wizard_apply_handler(const struct ast_sorcery *sorcery, struct object
char *hosts = ast_strdupa(remote_hosts);
while ((host = ast_strsep(&hosts, ',', AST_STRSEP_TRIM))) {
- AST_VECTOR_APPEND(&remote_hosts_vector, ast_strdup(host));
+ host = ast_strdup(host);
+ if (host && AST_VECTOR_APPEND(&remote_hosts_vector, host)) {
+ ast_free(host);
+ }
}
}
@@ -1168,15 +1171,22 @@ static void wizard_mapped_observer(const char *name, struct ast_sorcery *sorcery
/* We're only interested in memory wizards with the pjsip_wizard tag. */
if (wizard_args && !strcmp(wizard_args, "pjsip_wizard")) {
otw = ast_malloc(sizeof(*otw) + strlen(object_type) + 1);
+ if (!otw) {
+ return;
+ }
+
otw->sorcery = sorcery;
otw->wizard = wizard;
otw->wizard_data = wizard_data;
otw->last_config = NULL;
strcpy(otw->object_type, object_type); /* Safe */
AST_VECTOR_RW_WRLOCK(&object_type_wizards);
- AST_VECTOR_APPEND(&object_type_wizards, otw);
+ if (AST_VECTOR_APPEND(&object_type_wizards, otw)) {
+ ast_free(otw);
+ } else {
+ ast_debug(1, "Wizard mapped for object_type '%s'\n", object_type);
+ }
AST_VECTOR_RW_UNLOCK(&object_type_wizards);
- ast_debug(1, "Wizard mapped for object_type '%s'\n", object_type);
}
}
diff --git a/res/res_pjsip_exten_state.c b/res/res_pjsip_exten_state.c
index 95a40829e..3e756134c 100644
--- a/res/res_pjsip_exten_state.c
+++ b/res/res_pjsip_exten_state.c
@@ -729,8 +729,11 @@ static int exten_state_publisher_state_cb(const char *context, const char *exten
}
ao2_ref(publisher, +1);
- AST_VECTOR_APPEND(&pub_data->pubs, publisher);
- ast_debug(5, "'%s' will publish exten state\n", publisher->name);
+ if (AST_VECTOR_APPEND(&pub_data->pubs, publisher)) {
+ ao2_ref(publisher, -1);
+ } else {
+ ast_debug(5, "'%s' will publish exten state\n", publisher->name);
+ }
}
ao2_iterator_destroy(&publisher_iter);
diff --git a/res/res_pjsip_history.c b/res/res_pjsip_history.c
index 4e7dbd007..ed374d605 100644
--- a/res/res_pjsip_history.c
+++ b/res/res_pjsip_history.c
@@ -705,10 +705,13 @@ static pj_status_t history_on_tx_msg(pjsip_tx_data *tdata)
pj_sockaddr_cp(&entry->dst, &tdata->tp_info.dst_addr);
ast_mutex_lock(&history_lock);
- AST_VECTOR_APPEND(&vector_history, entry);
+ if (AST_VECTOR_APPEND(&vector_history, entry)) {
+ ao2_ref(entry, -1);
+ entry = NULL;
+ }
ast_mutex_unlock(&history_lock);
- if (log_level != -1) {
+ if (log_level != -1 && entry) {
char line[256];
sprint_list_entry(entry, line, sizeof(line));
@@ -745,10 +748,13 @@ static pj_bool_t history_on_rx_msg(pjsip_rx_data *rdata)
}
ast_mutex_lock(&history_lock);
- AST_VECTOR_APPEND(&vector_history, entry);
+ if (AST_VECTOR_APPEND(&vector_history, entry)) {
+ ao2_ref(entry, -1);
+ entry = NULL;
+ }
ast_mutex_unlock(&history_lock);
- if (log_level != -1) {
+ if (log_level != -1 && entry) {
char line[256];
sprint_list_entry(entry, line, sizeof(line));
@@ -959,7 +965,9 @@ static int evaluate_history_entry(struct pjsip_history_entry *entry, struct expr
/* If this is not an operator, push it to the stack */
if (!it_queue->op) {
- AST_VECTOR_APPEND(&stack, it_queue);
+ if (AST_VECTOR_APPEND(&stack, it_queue)) {
+ goto error;
+ }
continue;
}
@@ -1035,7 +1043,11 @@ static int evaluate_history_entry(struct pjsip_history_entry *entry, struct expr
if (!result) {
goto error;
}
- AST_VECTOR_APPEND(&stack, result);
+ if (AST_VECTOR_APPEND(&stack, result)) {
+ expression_token_free(result);
+
+ goto error;
+ }
}
/*
@@ -1056,6 +1068,7 @@ static int evaluate_history_entry(struct pjsip_history_entry *entry, struct expr
}
result = final->result;
ast_free(final);
+ AST_VECTOR_FREE(&stack);
return result;
@@ -1098,6 +1111,7 @@ static struct vector_history_t *filter_history(struct ast_cli_args *a)
queue = build_expression_queue(a);
if (!queue) {
+ AST_VECTOR_PTR_FREE(output);
return NULL;
}
@@ -1118,7 +1132,9 @@ static struct vector_history_t *filter_history(struct ast_cli_args *a)
} else if (!res) {
continue;
} else {
- AST_VECTOR_APPEND(output, ao2_bump(entry));
+ if (AST_VECTOR_APPEND(output, ao2_bump(entry))) {
+ ao2_cleanup(entry);
+ }
}
}
ast_mutex_unlock(&history_lock);
diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c
index 7fa6e2c10..d9afcd284 100644
--- a/res/res_pjsip_outbound_registration.c
+++ b/res/res_pjsip_outbound_registration.c
@@ -1385,10 +1385,10 @@ static int sip_outbound_registration_perform(void *data)
AST_VECTOR_INIT(&state->client_state->outbound_auths, AST_VECTOR_SIZE(&registration->outbound_auths));
for (i = 0; i < AST_VECTOR_SIZE(&registration->outbound_auths); ++i) {
- const char *name = ast_strdup(AST_VECTOR_GET(&registration->outbound_auths, i));
+ char *name = ast_strdup(AST_VECTOR_GET(&registration->outbound_auths, i));
- if (name) {
- AST_VECTOR_APPEND(&state->client_state->outbound_auths, name);
+ if (name && AST_VECTOR_APPEND(&state->client_state->outbound_auths, name)) {
+ ast_free(name);
}
}
state->client_state->retry_interval = registration->retry_interval;
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 62b187951..42b1a659b 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -938,7 +938,9 @@ static void build_node_children(struct ast_sip_endpoint *endpoint, const struct
}
ast_debug(2, "Subscription to leaf resource %s resulted in success. Adding to parent %s\n",
resource, parent->resource);
- AST_VECTOR_APPEND(&parent->children, current);
+ if (AST_VECTOR_APPEND(&parent->children, current)) {
+ tree_node_destroy(current);
+ }
} else {
ast_debug(2, "Subscription to leaf resource %s resulted in error response %d\n",
resource, resp);
@@ -953,7 +955,9 @@ static void build_node_children(struct ast_sip_endpoint *endpoint, const struct
build_node_children(endpoint, handler, child_list, current, visited);
if (AST_VECTOR_SIZE(&current->children) > 0) {
ast_debug(1, "List %s had no successful children.\n", resource);
- AST_VECTOR_APPEND(&parent->children, current);
+ if (AST_VECTOR_APPEND(&parent->children, current)) {
+ tree_node_destroy(current);
+ }
} else {
ast_debug(2, "List %s had successful children. Adding to parent %s\n",
resource, parent->resource);
@@ -1194,6 +1198,10 @@ static struct ast_sip_subscription *create_virtual_subscriptions(const struct as
if (AST_VECTOR_APPEND(&sub->children, child)) {
ast_debug(1, "Child subscription to resource %s could not be appended\n",
child_node->resource);
+ destroy_subscription(child);
+ /* Have to release tree here too because a ref was added
+ * to child that destroy_subscription() doesn't release. */
+ ao2_cleanup(tree);
}
}
@@ -2139,7 +2147,9 @@ static void build_body_part(pj_pool_t *pool, struct ast_sip_subscription *sub,
bp->part->body = body;
pj_list_insert_before(&bp->part->hdr, bp->cid);
- AST_VECTOR_APPEND(parts, bp);
+ if (AST_VECTOR_APPEND(parts, bp)) {
+ ast_free(bp);
+ }
}
/*!
@@ -2200,6 +2210,7 @@ static pjsip_msg_body *generate_list_body(pj_pool_t *pool, struct ast_sip_subscr
/* This can happen if issuing partial state and no children of the list have changed state */
if (AST_VECTOR_SIZE(&body_parts) == 0) {
+ free_body_parts(&body_parts);
return NULL;
}
@@ -2207,6 +2218,7 @@ static pjsip_msg_body *generate_list_body(pj_pool_t *pool, struct ast_sip_subscr
rlmi_part = build_rlmi_body(pool, sub, &body_parts, use_full_state);
if (!rlmi_part) {
+ free_body_parts(&body_parts);
return NULL;
}
pjsip_multipart_add_part(pool, multipart, rlmi_part);
@@ -4602,7 +4614,10 @@ static int list_item_handler(const struct aco_option *opt,
ast_log(LOG_WARNING, "Ignoring duplicated list item '%s'\n", item);
continue;
}
- if (AST_VECTOR_APPEND(&list->items, ast_strdup(item))) {
+
+ item = ast_strdup(item);
+ if (!item || AST_VECTOR_APPEND(&list->items, item)) {
+ ast_free(item);
return -1;
}
}
@@ -4738,7 +4753,10 @@ static int populate_list(struct resource_list *list, const char *event, const ch
ast_copy_string(list->event, event, sizeof(list->event));
for (i = 0; i < num_resources; ++i) {
- if (AST_VECTOR_APPEND(&list->items, ast_strdup(resources[i]))) {
+ char *resource = ast_strdup(resources[i]);
+
+ if (!resource || AST_VECTOR_APPEND(&list->items, resource)) {
+ ast_free(resource);
return -1;
}
}
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 4724d46ce..781d3e4eb 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -174,7 +174,8 @@ void ast_sip_session_unregister_sdp_handler(struct ast_sip_session_sdp_handler *
ao2_callback_data(sdp_handlers, OBJ_KEY | OBJ_UNLINK | OBJ_NODATA, remove_handler, (void *)stream_type, handler);
}
-struct ast_sip_session_media_state *ast_sip_session_media_state_alloc(void)
+static struct ast_sip_session_media_state *internal_sip_session_media_state_alloc(
+ size_t sessions, size_t read_callbacks)
{
struct ast_sip_session_media_state *media_state;
@@ -183,12 +184,12 @@ struct ast_sip_session_media_state *ast_sip_session_media_state_alloc(void)
return NULL;
}
- if (AST_VECTOR_INIT(&media_state->sessions, DEFAULT_NUM_SESSION_MEDIA) < 0) {
+ if (AST_VECTOR_INIT(&media_state->sessions, sessions) < 0) {
ast_free(media_state);
return NULL;
}
- if (AST_VECTOR_INIT(&media_state->read_callbacks, DEFAULT_NUM_SESSION_MEDIA) < 0) {
+ if (AST_VECTOR_INIT(&media_state->read_callbacks, read_callbacks) < 0) {
AST_VECTOR_FREE(&media_state->sessions);
ast_free(media_state);
return NULL;
@@ -197,6 +198,12 @@ struct ast_sip_session_media_state *ast_sip_session_media_state_alloc(void)
return media_state;
}
+struct ast_sip_session_media_state *ast_sip_session_media_state_alloc(void)
+{
+ return internal_sip_session_media_state_alloc(
+ DEFAULT_NUM_SESSION_MEDIA, DEFAULT_NUM_SESSION_MEDIA);
+}
+
void ast_sip_session_media_state_reset(struct ast_sip_session_media_state *media_state)
{
int index;
@@ -225,7 +232,9 @@ struct ast_sip_session_media_state *ast_sip_session_media_state_clone(const stru
return NULL;
}
- cloned = ast_sip_session_media_state_alloc();
+ cloned = internal_sip_session_media_state_alloc(
+ AST_VECTOR_SIZE(&media_state->sessions),
+ AST_VECTOR_SIZE(&media_state->read_callbacks));
if (!cloned) {
return NULL;
}
@@ -452,7 +461,11 @@ struct ast_sip_session_media *ast_sip_session_media_state_add(struct ast_sip_ses
}
}
- AST_VECTOR_REPLACE(&media_state->sessions, position, session_media);
+ if (AST_VECTOR_REPLACE(&media_state->sessions, position, session_media)) {
+ ao2_ref(session_media, -1);
+
+ return NULL;
+ }
/* If this stream will be active in some way and it is the first of this type then consider this the default media session to match */
if (!media_state->default_session[type] && ast_stream_get_state(ast_stream_topology_get_stream(media_state->topology, position)) != AST_STREAM_STATE_REMOVED) {
@@ -678,7 +691,10 @@ static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sd
if (!stream) {
return -1;
}
- ast_stream_topology_set_stream(session->pending_media_state->topology, i, stream);
+ if (ast_stream_topology_set_stream(session->pending_media_state->topology, i, stream)) {
+ ast_stream_free(stream);
+ return -1;
+ }
}
session_media = ast_sip_session_media_state_add(session, session->pending_media_state, ast_media_type_from_str(media), i);
@@ -1588,7 +1604,11 @@ int ast_sip_session_refresh(struct ast_sip_session *session,
}
ast_stream_set_state(cloned, AST_STREAM_STATE_REMOVED);
- ast_stream_topology_append_stream(media_state->topology, cloned);
+ if (ast_stream_topology_append_stream(media_state->topology, cloned) < 0) {
+ ast_stream_free(cloned);
+ ast_sip_session_media_state_free(media_state);
+ return -1;
+ }
}
/* If the resulting media state matches the existing active state don't bother doing a session refresh */
@@ -1745,7 +1765,10 @@ static int sdp_requires_deferral(struct ast_sip_session *session, const pjmedia_
/* As this is only called on an incoming SDP offer before processing it is not possible
* for streams and their media sessions to exist.
*/
- ast_stream_topology_set_stream(session->pending_media_state->topology, i, stream);
+ if (ast_stream_topology_set_stream(session->pending_media_state->topology, i, stream)) {
+ ast_stream_free(stream);
+ return -1;
+ }
session_media = ast_sip_session_media_state_add(session, session->pending_media_state, ast_media_type_from_str(media), i);
if (!session_media) {
@@ -3459,6 +3482,36 @@ static void session_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e)
/* XXX STUB */
}
+static int session_end_if_disconnected(int id, pjsip_inv_session *inv)
+{
+ struct ast_sip_session *session;
+
+ if (inv->state != PJSIP_INV_STATE_DISCONNECTED) {
+ return 0;
+ }
+
+ /*
+ * We are locking because ast_sip_dialog_get_session() needs
+ * the dialog locked to get the session by other threads.
+ */
+ pjsip_dlg_inc_lock(inv->dlg);
+ session = inv->mod_data[id];
+ inv->mod_data[id] = NULL;
+ pjsip_dlg_dec_lock(inv->dlg);
+
+ /*
+ * Pass the session ref held by session->inv_session to
+ * session_end_completion().
+ */
+ if (session
+ && ast_sip_push_task(session->serializer, session_end_completion, session)) {
+ /* Do it anyway even though this is not the right thread. */
+ session_end_completion(session);
+ }
+
+ return 1;
+}
+
static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e)
{
ast_sip_session_response_cb cb;
@@ -3483,6 +3536,17 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
/* The session has ended. Ignore the transaction change. */
return;
}
+
+ /*
+ * If the session is disconnected really nothing else to do unless currently transacting
+ * a BYE. If a BYE then hold off destruction until the transaction timeout occurs. This
+ * has to be done for BYEs because sometimes the dialog can be in a disconnected
+ * state but the BYE request transaction has not yet completed.
+ */
+ if (tsx->method.id != PJSIP_BYE_METHOD && session_end_if_disconnected(id, inv)) {
+ return;
+ }
+
switch (e->body.tsx_state.type) {
case PJSIP_EVENT_TX_MSG:
/* When we create an outgoing request, we do not have access to the transaction that
@@ -3605,49 +3669,12 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
}
break;
case PJSIP_EVENT_TRANSPORT_ERROR:
- if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
- /*
- * Clear the module data now to block session_inv_on_state_changed()
- * from calling session_end() if it hasn't already done so.
- */
- inv->mod_data[id] = NULL;
-
- /*
- * Pass the session ref held by session->inv_session to
- * session_end_completion().
- */
- if (session
- && ast_sip_push_task(session->serializer, session_end_completion, session)) {
- /* Do it anyway even though this is not the right thread. */
- session_end_completion(session);
- }
- return;
- }
- break;
case PJSIP_EVENT_TIMER:
/*
* The timer event is run by the pjsip monitor thread and not
* by the session serializer.
*/
- if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
- /*
- * We are locking because ast_sip_dialog_get_session() needs
- * the dialog locked to get the session by other threads.
- */
- pjsip_dlg_inc_lock(inv->dlg);
- session = inv->mod_data[id];
- inv->mod_data[id] = NULL;
- pjsip_dlg_dec_lock(inv->dlg);
-
- /*
- * Pass the session ref held by session->inv_session to
- * session_end_completion().
- */
- if (session
- && ast_sip_push_task(session->serializer, session_end_completion, session)) {
- /* Do it anyway even though this is not the right thread. */
- session_end_completion(session);
- }
+ if (session_end_if_disconnected(id, inv)) {
return;
}
break;
diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
index 48cbab37b..8f1905f6e 100644
--- a/res/res_pjsip_t38.c
+++ b/res/res_pjsip_t38.c
@@ -363,7 +363,11 @@ static struct ast_sip_session_media_state *t38_create_media_state(struct ast_sip
}
ast_stream_set_state(stream, AST_STREAM_STATE_SENDRECV);
- ast_stream_topology_set_stream(media_state->topology, 0, stream);
+ if (ast_stream_topology_set_stream(media_state->topology, 0, stream)) {
+ ast_stream_free(stream);
+ ast_sip_session_media_state_free(media_state);
+ return NULL;
+ }
caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!caps) {
@@ -371,9 +375,14 @@ static struct ast_sip_session_media_state *t38_create_media_state(struct ast_sip
return NULL;
}
- ast_format_cap_append(caps, ast_format_t38, 0);
ast_stream_set_formats(stream, caps);
+ /* stream holds a reference to cap, release the local reference
+ * now so we don't have to deal with it in the error condition. */
ao2_ref(caps, -1);
+ if (ast_format_cap_append(caps, ast_format_t38, 0)) {
+ ast_sip_session_media_state_free(media_state);
+ return NULL;
+ }
session_media = ast_sip_session_media_state_add(session, media_state, AST_MEDIA_TYPE_IMAGE, 0);
if (!session_media) {
diff --git a/res/res_stasis_playback.c b/res/res_stasis_playback.c
index c6f21365b..ca0446b89 100644
--- a/res/res_stasis_playback.c
+++ b/res/res_stasis_playback.c
@@ -497,7 +497,11 @@ struct stasis_app_playback *stasis_app_control_play_uri(
/* safe */
strcpy(media_uri, media[i]);
- AST_VECTOR_APPEND(&playback->medias, media_uri);
+ if (AST_VECTOR_APPEND(&playback->medias, media_uri)) {
+ ao2_ref(playback, -1);
+ ast_free(media_uri);
+ return NULL;
+ }
}
if (skipms == 0) {
diff --git a/res/stasis/app.c b/res/stasis/app.c
index 0b44bf3c6..a1ef5c0b6 100644
--- a/res/stasis/app.c
+++ b/res/stasis/app.c
@@ -588,6 +588,7 @@ static int message_received_handler(const char *endpoint_id, struct ast_json *js
{
RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup);
struct ast_json *json_endpoint;
+ struct ast_json *message;
struct stasis_app *app = pvt;
char *tech;
char *resource;
@@ -613,11 +614,15 @@ static int message_received_handler(const char *endpoint_id, struct ast_json *js
return -1;
}
- app_send(app, ast_json_pack("{s: s, s: o, s: o, s: o}",
+ message = ast_json_pack("{s: s, s: o, s: o, s: o}",
"type", "TextMessageReceived",
"timestamp", ast_json_timeval(ast_tvnow(), NULL),
"endpoint", json_endpoint,
- "message", ast_json_ref(json_msg)));
+ "message", ast_json_ref(json_msg));
+ if (message) {
+ app_send(app, message);
+ ast_json_unref(message);
+ }
return 0;
}
diff --git a/res/stasis/messaging.c b/res/stasis/messaging.c
index d398bb6d4..77a58745a 100644
--- a/res/stasis/messaging.c
+++ b/res/stasis/messaging.c
@@ -457,7 +457,11 @@ static struct message_subscription *get_or_create_subscription(struct ast_endpoi
ao2_link(endpoint_subscriptions, sub);
} else {
ast_rwlock_wrlock(&tech_subscriptions_lock);
- AST_VECTOR_APPEND(&tech_subscriptions, ao2_bump(sub));
+ if (AST_VECTOR_APPEND(&tech_subscriptions, ao2_bump(sub))) {
+ /* Release the ao2_bump that was for the vector and allocation references. */
+ ao2_ref(sub, -2);
+ sub = NULL;
+ }
ast_rwlock_unlock(&tech_subscriptions_lock);
}
@@ -485,7 +489,11 @@ int messaging_app_subscribe_endpoint(const char *app_name, struct ast_endpoint *
ao2_unlock(sub);
return -1;
}
- AST_VECTOR_APPEND(&sub->applications, tuple);
+ if (AST_VECTOR_APPEND(&sub->applications, tuple)) {
+ ao2_ref(tuple, -1);
+ ao2_unlock(sub);
+ return -1;
+ }
ao2_unlock(sub);
ast_debug(3, "App '%s' subscribed to messages from endpoint '%s'\n", app_name, endpoint ? ast_endpoint_get_id(endpoint) : "-- ALL --");