summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_queue.c21
-rw-r--r--cdr/cdr_adaptive_odbc.c22
-rw-r--r--cel/cel_odbc.c23
-rw-r--r--cel/cel_pgsql.c20
-rw-r--r--channels/chan_pjsip.c4
-rw-r--r--channels/chan_sip.c54
-rw-r--r--main/sched.c141
-rw-r--r--res/res_config_sqlite.c8
-rw-r--r--res/res_pjsip_diversion.c4
-rw-r--r--res/res_pjsip_pubsub.c33
10 files changed, 231 insertions, 99 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c
index bb3ec1790..23f69853d 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -5582,6 +5582,10 @@ struct queue_stasis_data {
struct local_optimization caller_optimize;
/*! Local channel optimization details for the member */
struct local_optimization member_optimize;
+ /*! Member channel */
+ struct ast_channel *member_channel;
+ /*! Caller channel */
+ struct ast_channel *caller_channel;
};
/*!
@@ -5599,6 +5603,9 @@ static void queue_stasis_data_destructor(void *obj)
ao2_cleanup(queue_data->member);
queue_unref(queue_data->queue);
ast_string_field_free_memory(queue_data);
+
+ ao2_ref(queue_data->member_channel, -1);
+ ao2_ref(queue_data->caller_channel, -1);
}
/*!
@@ -5645,6 +5652,16 @@ static struct queue_stasis_data *queue_stasis_data_alloc(struct queue_ent *qe,
queue_data->caller_pos = qe->opos;
ao2_ref(mem, +1);
queue_data->member = mem;
+
+ /*
+ * During transfers it's possible for both the member and/or caller
+ * channel(s) to not be available. Adding a reference here ensures
+ * that the channels remain until app_queue is completely done with
+ * them.
+ */
+ queue_data->member_channel = ao2_bump(peer);
+ queue_data->caller_channel = ao2_bump(qe->chan);
+
return queue_data;
}
@@ -6016,7 +6033,9 @@ static void handle_hangup(void *userdata, struct stasis_subscription *sub,
}
chan = ast_channel_get_by_name(channel_blob->snapshot->name);
- if (chan && ast_channel_has_role(chan, AST_TRANSFERER_ROLE_NAME)) {
+ if (chan && (ast_channel_has_role(chan, AST_TRANSFERER_ROLE_NAME) ||
+ !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "ATTENDEDTRANSFER")) ||
+ !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER")))) {
/* Channel that is hanging up is doing it as part of a transfer.
* We'll get a transfer event later
*/
diff --git a/cdr/cdr_adaptive_odbc.c b/cdr/cdr_adaptive_odbc.c
index 8bd9d0da6..0da8c0142 100644
--- a/cdr/cdr_adaptive_odbc.c
+++ b/cdr/cdr_adaptive_odbc.c
@@ -358,11 +358,11 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
return stmt;
}
-#define LENGTHEN_BUF1(size) \
+#define LENGTHEN_BUF(size, var_sql) \
do { \
/* Lengthen buffer, if necessary */ \
- if (ast_str_strlen(sql) + size + 1 > ast_str_size(sql)) { \
- if (ast_str_make_space(&sql, ((ast_str_size(sql) + size + 1) / 512 + 1) * 512) != 0) { \
+ if (ast_str_strlen(var_sql) + size + 1 > ast_str_size(var_sql)) { \
+ if (ast_str_make_space(&var_sql, ((ast_str_size(var_sql) + size + 1) / 512 + 1) * 512) != 0) { \
ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CDR '%s:%s' failed.\n", tableptr->connection, tableptr->table); \
ast_free(sql); \
ast_free(sql2); \
@@ -372,18 +372,10 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
} \
} while (0)
-#define LENGTHEN_BUF2(size) \
- do { \
- if (ast_str_strlen(sql2) + size + 1 > ast_str_size(sql2)) { \
- if (ast_str_make_space(&sql2, ((ast_str_size(sql2) + size + 3) / 512 + 1) * 512) != 0) { \
- ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CDR '%s:%s' failed.\n", tableptr->connection, tableptr->table); \
- ast_free(sql); \
- ast_free(sql2); \
- AST_RWLIST_UNLOCK(&odbc_tables); \
- return -1; \
- } \
- } \
- } while (0)
+#define LENGTHEN_BUF1(size) \
+ LENGTHEN_BUF(size, sql);
+#define LENGTHEN_BUF2(size) \
+ LENGTHEN_BUF(size, sql2);
static int odbc_log(struct ast_cdr *cdr)
{
diff --git a/cel/cel_odbc.c b/cel/cel_odbc.c
index 2d8408baa..3c0be04e8 100644
--- a/cel/cel_odbc.c
+++ b/cel/cel_odbc.c
@@ -341,11 +341,11 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
return stmt;
}
-#define LENGTHEN_BUF1(size) \
+#define LENGTHEN_BUF(size, var_sql) \
do { \
/* Lengthen buffer, if necessary */ \
- if (ast_str_strlen(sql) + size + 1 > ast_str_size(sql)) { \
- if (ast_str_make_space(&sql, ((ast_str_size(sql) + size + 1) / 512 + 1) * 512) != 0) { \
+ if (ast_str_strlen(var_sql) + size + 1 > ast_str_size(var_sql)) { \
+ if (ast_str_make_space(&var_sql, ((ast_str_size(var_sql) + size + 1) / 512 + 1) * 512) != 0) { \
ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CEL '%s:%s' failed.\n", tableptr->connection, tableptr->table); \
ast_free(sql); \
ast_free(sql2); \
@@ -355,18 +355,11 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
} \
} while (0)
-#define LENGTHEN_BUF2(size) \
- do { \
- if (ast_str_strlen(sql2) + size + 1 > ast_str_size(sql2)) { \
- if (ast_str_make_space(&sql2, ((ast_str_size(sql2) + size + 3) / 512 + 1) * 512) != 0) { \
- ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CEL '%s:%s' failed.\n", tableptr->connection, tableptr->table); \
- ast_free(sql); \
- ast_free(sql2); \
- AST_RWLIST_UNLOCK(&odbc_tables); \
- return; \
- } \
- } \
- } while (0)
+#define LENGTHEN_BUF1(size) \
+ LENGTHEN_BUF(size, sql);
+
+#define LENGTHEN_BUF2(size) \
+ LENGTHEN_BUF(size, sql2);
static void odbc_log(struct ast_event *event)
{
diff --git a/cel/cel_pgsql.c b/cel/cel_pgsql.c
index f4959474a..e4e280e41 100644
--- a/cel/cel_pgsql.c
+++ b/cel/cel_pgsql.c
@@ -100,11 +100,11 @@ struct columns {
static AST_RWLIST_HEAD_STATIC(psql_columns, columns);
-#define LENGTHEN_BUF1(size) \
+#define LENGTHEN_BUF(size, var_sql) \
do { \
/* Lengthen buffer, if necessary */ \
- if (ast_str_strlen(sql) + size + 1 > ast_str_size(sql)) { \
- if (ast_str_make_space(&sql, ((ast_str_size(sql) + size + 3) / 512 + 1) * 512) != 0) { \
+ if (ast_str_strlen(var_sql) + size + 1 > ast_str_size(var_sql)) { \
+ if (ast_str_make_space(&var_sql, ((ast_str_size(var_sql) + size + 3) / 512 + 1) * 512) != 0) { \
ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CEL '%s:%s' failed.\n", pghostname, table); \
ast_free(sql); \
ast_free(sql2); \
@@ -114,18 +114,10 @@ static AST_RWLIST_HEAD_STATIC(psql_columns, columns);
} \
} while (0)
+#define LENGTHEN_BUF1(size) \
+ LENGTHEN_BUF(size, sql);
#define LENGTHEN_BUF2(size) \
- do { \
- if (ast_str_strlen(sql2) + size + 1 > ast_str_size(sql2)) { \
- if (ast_str_make_space(&sql2, ((ast_str_size(sql2) + size + 3) / 512 + 1) * 512) != 0) { \
- ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CEL '%s:%s' failed.\n", pghostname, table); \
- ast_free(sql); \
- ast_free(sql2); \
- AST_RWLIST_UNLOCK(&psql_columns); \
- return; \
- } \
- } \
- } while (0)
+ LENGTHEN_BUF(size, sql2);
static void pgsql_reconnect(void)
{
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 9603f0514..153b2a33b 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -160,10 +160,10 @@ static struct ast_sip_session_supplement chan_pjsip_ack_supplement = {
static enum ast_rtp_glue_result chan_pjsip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
- struct chan_pjsip_pvt *pvt = channel->pvt;
+ struct chan_pjsip_pvt *pvt;
struct ast_sip_endpoint *endpoint;
- if (!pvt || !channel->session || !pvt->media[SIP_MEDIA_AUDIO]->rtp) {
+ if (!channel || !channel->session || !(pvt = channel->pvt) || !pvt->media[SIP_MEDIA_AUDIO]->rtp) {
return AST_RTP_GLUE_RESULT_FORBID;
}
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index f96a80f3b..8d5af2f09 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -13940,6 +13940,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
int cid_has_name = 1;
int cid_has_num = 1;
struct ast_party_id connected_id;
+ int ret;
if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) {
const char *s = p->username; /* being a string field, cannot be NULL */
@@ -14024,26 +14025,41 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
ast_copy_string(tmp_l, l, sizeof(tmp_l));
if (sip_cfg.pedanticsipchecking) {
- ast_escape_quoted(n, tmp_n, sizeof(tmp_n));
- n = tmp_n;
ast_uri_encode(l, tmp_l, sizeof(tmp_l), ast_uri_sip_user);
}
ourport = (p->fromdomainport && (p->fromdomainport != STANDARD_SIP_PORT)) ? p->fromdomainport : ast_sockaddr_port(&p->ourip);
- /* If a caller id name was specified, add a display name. */
- if (cid_has_name || !cid_has_num) {
- snprintf(from, sizeof(from), "\"%s\" ", n);
+ if (!sip_standard_port(p->socket.type, ourport)) {
+ ret = snprintf(from, sizeof(from), "<sip:%s@%s:%d>;tag=%s", tmp_l, d, ourport, p->tag);
} else {
- from[0] = '\0';
+ ret = snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", tmp_l, d, p->tag);
+ }
+ if (ret < 0 || ret >= sizeof(from)) { /* a return value of size or more means that the output was truncated */
+ /* We don't have an escape path from here... */
+ ast_log(LOG_ERROR, "The From header was truncated in call '%s'. This call setup will fail.\n", p->callid);
}
- if (!sip_standard_port(p->socket.type, ourport)) {
- size_t offset = strlen(from);
- snprintf(&from[offset], sizeof(from) - offset, "<sip:%s@%s:%d>;tag=%s", tmp_l, d, ourport, p->tag);
- } else {
- size_t offset = strlen(from);
- snprintf(&from[offset], sizeof(from) - offset, "<sip:%s@%s>;tag=%s", tmp_l, d, p->tag);
+ /* If a caller id name was specified, prefix a display name, if there is enough room. */
+ if (cid_has_name || !cid_has_num) {
+ size_t written = strlen(from);
+ ssize_t left = sizeof(from) - written - 4; /* '"" \0' */
+ if (left > 0) {
+ size_t name_len;
+ if (sip_cfg.pedanticsipchecking) {
+ ast_escape_quoted(n, tmp_n, MIN(left + 1, sizeof(tmp_n)));
+ n = tmp_n;
+ }
+ name_len = strlen(n);
+ if (left < name_len) {
+ name_len = left;
+ }
+ memmove(from + name_len + 3, from, written + 1);
+ from[0] = '"';
+ memcpy(from + 1, n, name_len);
+ from[name_len + 1] = '"';
+ from[name_len + 2] = ' ';
+ }
}
if (!ast_strlen_zero(explicit_uri)) {
@@ -14085,21 +14101,25 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
/*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */
if (!strchr(p->todnid, '@')) {
/* We have no domain in the dnid */
- snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag);
+ ret = snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag);
} else {
- snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag);
+ ret = snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag);
}
} else {
if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) {
/* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */
- snprintf(to, sizeof(to), "<%s%s>;tag=%s", (strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag);
+ ret = snprintf(to, sizeof(to), "<%s%s>;tag=%s", (strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag);
} else if (p->options && p->options->vxml_url) {
/* If there is a VXML URL append it to the SIP URL */
- snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
+ ret = snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
} else {
- snprintf(to, sizeof(to), "<%s>", p->uri);
+ ret = snprintf(to, sizeof(to), "<%s>", p->uri);
}
}
+ if (ret < 0 || ret >= sizeof(to)) { /* a return value of size or more means that the output was truncated */
+ /* We don't have an escape path from here... */
+ ast_log(LOG_ERROR, "The To header was truncated in call '%s'. This call setup will fail.\n", p->callid);
+ }
init_req(req, sipmethod, p->uri);
/* now tmp_n is available so reuse it to build the CSeq */
diff --git a/main/sched.c b/main/sched.c
index 062b2fd96..8f9e84bff 100644
--- a/main/sched.c
+++ b/main/sched.c
@@ -62,9 +62,26 @@ ASTERISK_REGISTER_FILE()
AST_THREADSTORAGE(last_del_id);
+/*!
+ * \brief Scheduler ID holder
+ *
+ * These form a queue on a scheduler context. When a new
+ * scheduled item is created, a sched_id is popped off the
+ * queue and its id is assigned to the new scheduled item.
+ * When the scheduled task is complete, the sched_id on that
+ * task is then pushed to the back of the queue to be re-used
+ * on some future scheduled item.
+ */
+struct sched_id {
+ /*! Immutable ID number that is copied onto the scheduled task */
+ int id;
+ AST_LIST_ENTRY(sched_id) list;
+};
+
struct sched {
AST_LIST_ENTRY(sched) list;
- int id; /*!< ID number of event */
+ /*! The ID that has been popped off the scheduler context's queue */
+ struct sched_id *sched_id;
struct timeval when; /*!< Absolute time event should take place */
int resched; /*!< When to reschedule */
int variable; /*!< Use return value from callback to reschedule */
@@ -99,6 +116,10 @@ struct ast_sched_context {
AST_LIST_HEAD_NOLOCK(, sched) schedc; /*!< Cache of unused schedule structures and how many */
unsigned int schedccnt;
#endif
+ /*! Queue of scheduler task IDs to assign */
+ AST_LIST_HEAD_NOLOCK(, sched_id) id_queue;
+ /*! The number of IDs in the id_queue */
+ int id_queue_size;
};
static void *sched_run(void *data)
@@ -208,6 +229,8 @@ struct ast_sched_context *ast_sched_context_create(void)
ast_mutex_init(&tmp->lock);
tmp->eventcnt = 1;
+ AST_LIST_HEAD_INIT_NOLOCK(&tmp->id_queue);
+
if (!(tmp->sched_heap = ast_heap_create(8, sched_time_cmp,
offsetof(struct sched, __heap_index)))) {
ast_sched_context_destroy(tmp);
@@ -219,6 +242,11 @@ struct ast_sched_context *ast_sched_context_create(void)
static void sched_free(struct sched *task)
{
+ /* task->sched_id will be NULL most of the time, but when the
+ * scheduler context shuts down, it will free all scheduled
+ * tasks, and in that case, the task->sched_id will be non-NULL
+ */
+ ast_free(task->sched_id);
ast_cond_destroy(&task->cond);
ast_free(task);
}
@@ -226,6 +254,7 @@ static void sched_free(struct sched *task)
void ast_sched_context_destroy(struct ast_sched_context *con)
{
struct sched *s;
+ struct sched_id *sid;
sched_thread_destroy(con);
con->sched_thread = NULL;
@@ -246,40 +275,75 @@ void ast_sched_context_destroy(struct ast_sched_context *con)
con->sched_heap = NULL;
}
+ while ((sid = AST_LIST_REMOVE_HEAD(&con->id_queue, list))) {
+ ast_free(sid);
+ }
+
ast_mutex_unlock(&con->lock);
ast_mutex_destroy(&con->lock);
ast_free(con);
}
-static struct sched *sched_alloc(struct ast_sched_context *con)
-{
- struct sched *tmp;
+#define ID_QUEUE_INCREMENT 16
- /*
- * We keep a small cache of schedule entries
- * to minimize the number of necessary malloc()'s
+/*!
+ * \brief Add new scheduler IDs to the queue.
+ *
+ * \retval The number of IDs added to the queue
+ */
+static int add_ids(struct ast_sched_context *con)
+{
+ int new_size;
+ int original_size;
+ int i;
+
+ original_size = con->id_queue_size;
+ /* So we don't go overboard with the mallocs here, we'll just up
+ * the size of the list by a fixed amount each time instead of
+ * multiplying the size by any particular factor
*/
-#ifdef SCHED_MAX_CACHE
- if ((tmp = AST_LIST_REMOVE_HEAD(&con->schedc, list))) {
- con->schedccnt--;
- } else
-#endif
- {
- tmp = ast_calloc(1, sizeof(*tmp));
- ast_cond_init(&tmp->cond, NULL);
+ new_size = original_size + ID_QUEUE_INCREMENT;
+ if (new_size < 0) {
+ /* Overflow. Cap it at INT_MAX. */
+ new_size = INT_MAX;
}
+ for (i = original_size; i < new_size; ++i) {
+ struct sched_id *new_id;
- return tmp;
+ new_id = ast_calloc(1, sizeof(*new_id));
+ if (!new_id) {
+ break;
+ }
+ new_id->id = i;
+ AST_LIST_INSERT_TAIL(&con->id_queue, new_id, list);
+ ++con->id_queue_size;
+ }
+
+ return con->id_queue_size - original_size;
+}
+
+static int set_sched_id(struct ast_sched_context *con, struct sched *new_sched)
+{
+ if (AST_LIST_EMPTY(&con->id_queue) && (add_ids(con) == 0)) {
+ return -1;
+ }
+
+ new_sched->sched_id = AST_LIST_REMOVE_HEAD(&con->id_queue, list);
+ return 0;
}
static void sched_release(struct ast_sched_context *con, struct sched *tmp)
{
+ if (tmp->sched_id) {
+ AST_LIST_INSERT_TAIL(&con->id_queue, tmp->sched_id, list);
+ tmp->sched_id = NULL;
+ }
+
/*
* Add to the cache, or just free() if we
* already have too many cache entries
*/
-
#ifdef SCHED_MAX_CACHE
if (con->schedccnt < SCHED_MAX_CACHE) {
AST_LIST_INSERT_HEAD(&con->schedc, tmp, list);
@@ -289,6 +353,35 @@ static void sched_release(struct ast_sched_context *con, struct sched *tmp)
sched_free(tmp);
}
+static struct sched *sched_alloc(struct ast_sched_context *con)
+{
+ struct sched *tmp;
+
+ /*
+ * We keep a small cache of schedule entries
+ * to minimize the number of necessary malloc()'s
+ */
+#ifdef SCHED_MAX_CACHE
+ if ((tmp = AST_LIST_REMOVE_HEAD(&con->schedc, list))) {
+ con->schedccnt--;
+ } else
+#endif
+ {
+ tmp = ast_calloc(1, sizeof(*tmp));
+ if (!tmp) {
+ return NULL;
+ }
+ ast_cond_init(&tmp->cond, NULL);
+ }
+
+ if (set_sched_id(con, tmp)) {
+ sched_release(con, tmp);
+ return NULL;
+ }
+
+ return tmp;
+}
+
void ast_sched_clean_by_callback(struct ast_sched_context *con, ast_sched_cb match, ast_sched_cb cleanup_cb)
{
int i = 1;
@@ -388,7 +481,7 @@ int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb
ast_mutex_lock(&con->lock);
if ((tmp = sched_alloc(con))) {
- tmp->id = con->eventcnt++;
+ con->eventcnt++;
tmp->callback = callback;
tmp->data = data;
tmp->resched = when;
@@ -399,7 +492,7 @@ int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb
sched_release(con, tmp);
} else {
schedule(con, tmp);
- res = tmp->id;
+ res = tmp->sched_id->id;
}
}
#ifdef DUMP_SCHEDULER
@@ -437,7 +530,7 @@ static struct sched *sched_find(struct ast_sched_context *con, int id)
for (x = 1; x <= heap_size; x++) {
struct sched *cur = ast_heap_peek(con->sched_heap, x);
- if (cur->id == id) {
+ if (cur->sched_id->id == id) {
return cur;
}
}
@@ -488,16 +581,16 @@ int _ast_sched_del(struct ast_sched_context *con, int id, const char *file, int
s = sched_find(con, id);
if (s) {
if (!ast_heap_remove(con->sched_heap, s)) {
- ast_log(LOG_WARNING,"sched entry %d not in the sched heap?\n", s->id);
+ ast_log(LOG_WARNING,"sched entry %d not in the sched heap?\n", s->sched_id->id);
}
sched_release(con, s);
- } else if (con->currently_executing && (id == con->currently_executing->id)) {
+ } else if (con->currently_executing && (id == con->currently_executing->sched_id->id)) {
s = con->currently_executing;
s->deleted = 1;
/* Wait for executing task to complete so that caller of ast_sched_del() does not
* free memory out from under the task.
*/
- while (con->currently_executing && (id == con->currently_executing->id)) {
+ while (con->currently_executing && (id == con->currently_executing->sched_id->id)) {
ast_cond_wait(&s->cond, &con->lock);
}
/* Do not sched_release() here because ast_sched_runq() will do it */
@@ -586,7 +679,7 @@ void ast_sched_dump(struct ast_sched_context *con)
q = ast_heap_peek(con->sched_heap, x);
delta = ast_tvsub(q->when, when);
ast_debug(1, "|%.4d | %-15p | %-15p | %.6ld : %.6ld |\n",
- q->id,
+ q->sched_id->id,
q->callback,
q->data,
(long)delta.tv_sec,
diff --git a/res/res_config_sqlite.c b/res/res_config_sqlite.c
index 5659b4e41..4375c3960 100644
--- a/res/res_config_sqlite.c
+++ b/res/res_config_sqlite.c
@@ -781,8 +781,16 @@ static int cdr_handler(struct ast_cdr *cdr)
struct ast_str *sql1 = ast_str_create(160), *sql2 = ast_str_create(16);
int first = 1;
+ if (!sql1 || !sql2) {
+ ast_free(sql1);
+ ast_free(sql2);
+ return -1;
+ }
+
if (!tbl) {
ast_log(LOG_WARNING, "No such table: %s\n", cdr_table);
+ ast_free(sql1);
+ ast_free(sql2);
return -1;
}
diff --git a/res/res_pjsip_diversion.c b/res/res_pjsip_diversion.c
index 3dfae455b..ea2c7cd13 100644
--- a/res/res_pjsip_diversion.c
+++ b/res/res_pjsip_diversion.c
@@ -117,7 +117,9 @@ static void set_redirecting_value(char **dst, const pj_str_t *src)
{
ast_free(*dst);
*dst = ast_malloc(pj_strlen(src) + 1);
- ast_copy_pj_str(*dst, src, pj_strlen(src) + 1);
+ if (*dst) {
+ ast_copy_pj_str(*dst, src, pj_strlen(src) + 1);
+ }
}
static void set_redirecting_id(pjsip_name_addr *name_addr, struct ast_party_id *data,
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index e3b1024c0..7d84b4675 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -1306,7 +1306,7 @@ static struct sip_subscription_tree *create_subscription_tree(const struct ast_s
return sub_tree;
}
-static int generate_initial_notify(struct ast_sip_subscription *sub);
+static int initial_notify_task(void *obj);
static int send_notify(struct sip_subscription_tree *sub_tree, unsigned int force_full_state);
/*! \brief Callback function to perform the actual recreation of a subscription */
@@ -1404,10 +1404,9 @@ static int subscription_persistence_recreate(void *obj, void *arg, int flags)
}
sub_tree->persistence = ao2_bump(persistence);
subscription_persistence_update(sub_tree, &rdata);
- if (generate_initial_notify(sub_tree->root)) {
+ if (ast_sip_push_task(sub_tree->serializer, initial_notify_task, ao2_bump(sub_tree))) {
pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
- } else {
- send_notify(sub_tree, 1);
+ ao2_ref(sub_tree, -1);
}
} else {
ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
@@ -2545,6 +2544,24 @@ static int generate_initial_notify(struct ast_sip_subscription *sub)
return res;
}
+static int initial_notify_task(void * obj)
+{
+ struct sip_subscription_tree *sub_tree;
+
+ sub_tree = obj;
+ if (generate_initial_notify(sub_tree->root)) {
+ pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
+ } else {
+ send_notify(sub_tree, 1);
+ ast_test_suite_event_notify("SUBSCRIPTION_ESTABLISHED",
+ "Resource: %s",
+ sub_tree->root->resource);
+ }
+
+ ao2_ref(sub_tree, -1);
+ return 0;
+}
+
static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
{
pjsip_expires_hdr *expires_header;
@@ -2632,13 +2649,9 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
sub_tree->persistence = subscription_persistence_create(sub_tree);
subscription_persistence_update(sub_tree, rdata);
sip_subscription_accept(sub_tree, rdata, resp);
- if (generate_initial_notify(sub_tree->root)) {
+ if (ast_sip_push_task(sub_tree->serializer, initial_notify_task, ao2_bump(sub_tree))) {
pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
- } else {
- send_notify(sub_tree, 1);
- ast_test_suite_event_notify("SUBSCRIPTION_ESTABLISHED",
- "Resource: %s",
- sub_tree->root->resource);
+ ao2_ref(sub_tree, -1);
}
}