diff options
-rw-r--r-- | CHANGES | 6 | ||||
-rw-r--r-- | apps/app_queue.c | 66 | ||||
-rw-r--r-- | apps/app_voicemail.c | 3 | ||||
-rw-r--r-- | bridges/bridge_softmix.c | 46 | ||||
-rw-r--r-- | configs/samples/queues.conf.sample | 2 | ||||
-rw-r--r-- | contrib/ast-db-manage/config/versions/e2f04d309071_add_wrapuptime_to_queue_members.py | 22 | ||||
-rw-r--r-- | funcs/func_callerid.c | 18 | ||||
-rw-r--r-- | main/cel.c | 4 | ||||
-rw-r--r-- | main/rtp_engine.c | 60 |
9 files changed, 157 insertions, 70 deletions
@@ -37,6 +37,12 @@ ARI * The ContactInfo event's contact_status field is now set to "NonQualified" when a contact exists but has not been qualified. +app_queue +------------------ + * Added the ability to set the wrapuptime in the configuration of member. + When set the wrapuptime on the member is used instead of the wrapuptime + defined for the queue itself. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 15.1.0 to Asterisk 15.2.0 ------------ ------------------------------------------------------------------------------ diff --git a/apps/app_queue.c b/apps/app_queue.c index a140847c6..af8b3b88b 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -1,7 +1,7 @@ /* * Asterisk -- An open source telephony toolkit. * - * Copyright (C) 1999 - 2016, Digium, Inc. + * Copyright (C) 1999 - 2017, Digium, Inc. * * Mark Spencer <markster@digium.com> * @@ -1586,6 +1586,7 @@ struct member { char reason_paused[80]; /*!< Reason of paused if member is paused */ int queuepos; /*!< In what order (pertains to certain strategies) should this member be called? */ int callcompletedinsl; /*!< Whether the current call was completed within service level */ + int wrapuptime; /*!< Wrapup Time */ time_t starttime; /*!< The time at which the member answered the current caller. */ time_t lastcall; /*!< When last successful call was hungup */ time_t lastpause; /*!< When started the last pause */ @@ -1826,6 +1827,21 @@ static int queue_cmp_cb(void *obj, void *arg, int flags) return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0; } +/*! + * \brief Return wrapuptime + * + * This function checks if wrapuptime in member is set and return this value. + * Otherwise return value the wrapuptime in the queue configuration + * \return integer value + */ +static int get_wrapuptime(struct call_queue *q, struct member *member) +{ + if (member->wrapuptime) { + return member->wrapuptime; + } + return q->wrapuptime; +} + /*! \internal * \brief ao2_callback, Decreases queuepos of all followers with a queuepos greater than arg. * \param obj the member being acted on @@ -2309,8 +2325,12 @@ static int get_member_status(struct call_queue *q, int max_penalty, int min_pena if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) { ast_debug(4, "%s is unavailable because he is paused'\n", member->membername); break; - } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) { - ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime); + } else if ((conditions & QUEUE_EMPTY_WRAPUP) + && member->lastcall + && get_wrapuptime(q, member) + && (time(NULL) - get_wrapuptime(q, member) < member->lastcall)) { + ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", + member->membername, (int) (time(NULL) - member->lastcall), get_wrapuptime(q, member)); break; } else { ao2_ref(member, -1); @@ -2436,6 +2456,7 @@ static void update_status(struct call_queue *q, struct member *m, const int stat static int is_member_available(struct call_queue *q, struct member *mem) { int available = 0; + int wrapuptime; switch (mem->status) { case AST_DEVICE_INVALID: @@ -2459,7 +2480,8 @@ static int is_member_available(struct call_queue *q, struct member *mem) } /* Let wrapuptimes override device state availability */ - if (mem->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < mem->lastcall)) { + wrapuptime = get_wrapuptime(q, mem); + if (mem->lastcall && wrapuptime && (time(NULL) - wrapuptime < mem->lastcall)) { available = 0; } return available; @@ -3354,6 +3376,7 @@ static void rt_handle_member_record(struct call_queue *q, char *category, struct int penalty = 0; int paused = 0; int found = 0; + int wrapuptime = 0; int ringinuse = q->ringinuse; const char *config_val; @@ -3363,6 +3386,7 @@ static void rt_handle_member_record(struct call_queue *q, char *category, struct const char *state_interface = S_OR(ast_variable_retrieve(member_config, category, "state_interface"), interface); const char *penalty_str = ast_variable_retrieve(member_config, category, "penalty"); const char *paused_str = ast_variable_retrieve(member_config, category, "paused"); + const char *wrapuptime_str = ast_variable_retrieve(member_config, category, "wrapuptime"); if (ast_strlen_zero(rt_uniqueid)) { ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL")); @@ -3385,6 +3409,13 @@ static void rt_handle_member_record(struct call_queue *q, char *category, struct } } + if (wrapuptime_str) { + wrapuptime = atoi(wrapuptime_str); + if (wrapuptime < 0) { + wrapuptime = 0; + } + } + if ((config_val = ast_variable_retrieve(member_config, category, realtime_ringinuse_field))) { if (ast_true(config_val)) { ringinuse = 1; @@ -3411,6 +3442,7 @@ static void rt_handle_member_record(struct call_queue *q, char *category, struct } m->penalty = penalty; m->ringinuse = ringinuse; + m->wrapuptime = wrapuptime; found = 1; ao2_ref(m, -1); break; @@ -4343,6 +4375,8 @@ static int member_status_available(int status) */ static int can_ring_entry(struct queue_ent *qe, struct callattempt *call) { + int wrapuptime; + if (call->member->paused) { ast_debug(1, "%s paused, can't receive call\n", call->interface); return 0; @@ -4353,8 +4387,12 @@ static int can_ring_entry(struct queue_ent *qe, struct callattempt *call) return 0; } - if ((call->lastqueue && call->lastqueue->wrapuptime && (time(NULL) - call->lastcall < call->lastqueue->wrapuptime)) - || (!call->lastqueue && qe->parent->wrapuptime && (time(NULL) - call->lastcall < qe->parent->wrapuptime))) { + if (call->lastqueue) { + wrapuptime = get_wrapuptime(call->lastqueue, call->member); + } else { + wrapuptime = get_wrapuptime(qe->parent, call->member); + } + if (wrapuptime && time(NULL) - call->lastcall < wrapuptime) { ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n", (call->lastqueue ? call->lastqueue->name : qe->parent->name), call->interface); @@ -8554,7 +8592,7 @@ static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, ch while ((m = ao2_iterator_next(&mem_iter))) { /* Count the agents who are logged in, not paused and not wrapping up */ if ((m->status == AST_DEVICE_NOT_INUSE) && (!m->paused) && - !(m->lastcall && q->wrapuptime && ((now - q->wrapuptime) < m->lastcall))) { + !(m->lastcall && get_wrapuptime(q, m) && ((now - get_wrapuptime(q, m)) < m->lastcall))) { count++; } ao2_ref(m, -1); @@ -9098,12 +9136,14 @@ static void reload_single_member(const char *memberdata, struct call_queue *q) struct member tmpmem; int penalty; int ringinuse; + int wrapuptime; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(interface); AST_APP_ARG(penalty); AST_APP_ARG(membername); AST_APP_ARG(state_interface); AST_APP_ARG(ringinuse); + AST_APP_ARG(wrapuptime); ); if (ast_strlen_zero(memberdata)) { @@ -9158,11 +9198,23 @@ static void reload_single_member(const char *memberdata, struct call_queue *q) ringinuse = q->ringinuse; } + if (!ast_strlen_zero(args.wrapuptime)) { + tmp = args.wrapuptime; + ast_strip(tmp); + wrapuptime = atoi(tmp); + if (wrapuptime < 0) { + wrapuptime = 0; + } + } else { + wrapuptime = 0; + } + /* Find the old position in the list */ ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface)); cur = ao2_find(q->members, &tmpmem, OBJ_POINTER); if ((newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface, ringinuse))) { + newm->wrapuptime = wrapuptime; if (cur) { /* Round Robin Queue Position must be copied if this is replacing an existing member */ ao2_lock(q->members); diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index c155186a2..af2174ba9 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -5390,6 +5390,7 @@ plain_message: static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum) { char fname[PATH_MAX] = ""; + char sox_gain_tmpdir[PATH_MAX]; char *file_to_delete = NULL, *dir_to_delete = NULL; int res; @@ -5399,7 +5400,6 @@ static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format, /* This 'while' loop will only execute once. We use it so that we can 'break' */ while (vmu->volgain < -.001 || vmu->volgain > .001) { char tmpdir[PATH_MAX]; - char sox_gain_tmpdir[PATH_MAX]; create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp"); @@ -13167,6 +13167,7 @@ static void mwi_sub_event_cb(struct stasis_subscription_change *change) } if (separate_mailbox(ast_strdupa(stasis_topic_name(change->topic)), &mailbox, &context)) { + ast_free(mwist); return; } diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c index 8de88f257..83b1a8337 100644 --- a/bridges/bridge_softmix.c +++ b/bridges/bridge_softmix.c @@ -418,8 +418,9 @@ static void softmix_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridg */ static int is_video_source(const struct ast_stream *stream) { - if (ast_stream_get_type(stream) == AST_MEDIA_TYPE_VIDEO && - strncmp(ast_stream_get_name(stream), SOFTBRIDGE_VIDEO_DEST_PREFIX, + if (ast_stream_get_state(stream) != AST_STREAM_STATE_REMOVED + && ast_stream_get_type(stream) == AST_MEDIA_TYPE_VIDEO + && strncmp(ast_stream_get_name(stream), SOFTBRIDGE_VIDEO_DEST_PREFIX, SOFTBRIDGE_VIDEO_DEST_LEN)) { return 1; } @@ -448,40 +449,35 @@ static int is_video_dest(const struct ast_stream *stream, const char *source_cha char *dest_video_name; size_t dest_video_name_len; - if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_VIDEO) { + if (ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED + || ast_stream_get_type(stream) != AST_MEDIA_TYPE_VIDEO) { return 0; } dest_video_name_len = SOFTBRIDGE_VIDEO_DEST_LEN + 1; - if (!ast_strlen_zero(source_channel_name)) { dest_video_name_len += strlen(source_channel_name) + 1; if (!ast_strlen_zero(source_stream_name)) { dest_video_name_len += strlen(source_stream_name) + 1; } - } - dest_video_name = ast_alloca(dest_video_name_len); - if (!ast_strlen_zero(source_channel_name)) { + dest_video_name = ast_alloca(dest_video_name_len); if (!ast_strlen_zero(source_stream_name)) { + /* We are looking for an exact stream name */ snprintf(dest_video_name, dest_video_name_len, "%s%c%s%c%s", SOFTBRIDGE_VIDEO_DEST_PREFIX, SOFTBRIDGE_VIDEO_DEST_SEPARATOR, source_channel_name, SOFTBRIDGE_VIDEO_DEST_SEPARATOR, source_stream_name); return !strcmp(ast_stream_get_name(stream), dest_video_name); - } else { - snprintf(dest_video_name, dest_video_name_len, "%s%c%s", - SOFTBRIDGE_VIDEO_DEST_PREFIX, SOFTBRIDGE_VIDEO_DEST_SEPARATOR, - source_channel_name); - return !strncmp(ast_stream_get_name(stream), dest_video_name, dest_video_name_len - 1); } + snprintf(dest_video_name, dest_video_name_len, "%s%c%s", + SOFTBRIDGE_VIDEO_DEST_PREFIX, SOFTBRIDGE_VIDEO_DEST_SEPARATOR, + source_channel_name); } else { - snprintf(dest_video_name, dest_video_name_len, "%s", - SOFTBRIDGE_VIDEO_DEST_PREFIX); - return !strncmp(ast_stream_get_name(stream), dest_video_name, dest_video_name_len - 1); + dest_video_name = SOFTBRIDGE_VIDEO_DEST_PREFIX; } - return 0; + return !strncmp(ast_stream_get_name(stream), dest_video_name, dest_video_name_len - 1); } static int append_source_streams(struct ast_stream_topology *dest, @@ -672,6 +668,7 @@ static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chan ast_log(LOG_ERROR, "Bridge %s: Failed to join channel %s. " "Could not allocate enough memory.\n", bridge->uniqueid, ast_channel_name(bridge_channel->chan)); + ast_free(sc); return -1; } } @@ -697,10 +694,11 @@ static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chan return 0; } -static void remove_destination_streams(struct ast_stream_topology *topology, +static int remove_destination_streams(struct ast_stream_topology *topology, const char *channel_name) { int i; + int stream_removed = 0; for (i = 0; i < ast_stream_topology_get_count(topology); ++i) { struct ast_stream *stream; @@ -709,8 +707,10 @@ static void remove_destination_streams(struct ast_stream_topology *topology, if (is_video_dest(stream, channel_name, NULL)) { ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED); + stream_removed = 1; } } + return stream_removed; } static int sfu_topologies_on_leave(struct ast_bridge_channel *leaver, struct ast_bridge_channels_list *participants) @@ -720,13 +720,16 @@ static int sfu_topologies_on_leave(struct ast_bridge_channel *leaver, struct ast AST_LIST_TRAVERSE(participants, participant, entry) { sc = participant->tech_pvt; - remove_destination_streams(sc->topology, ast_channel_name(leaver->chan)); + if (!remove_destination_streams(sc->topology, ast_channel_name(leaver->chan))) { + continue; + } ast_channel_request_stream_topology_change(participant->chan, sc->topology, NULL); } sc = leaver->tech_pvt; - remove_destination_streams(sc->topology, ""); - ast_channel_request_stream_topology_change(leaver->chan, sc->topology, NULL); + if (remove_destination_streams(sc->topology, "")) { + ast_channel_request_stream_topology_change(leaver->chan, sc->topology, NULL); + } return 0; } @@ -1306,6 +1309,8 @@ static int softmix_mixing_array_grow(struct softmix_mixing_array *mixing_array, ast_log(LOG_NOTICE, "Failed to re-allocate softmix mixing structure.\n"); return -1; } + mixing_array->buffers = tmp; + if (binaural_active) { struct convolve_channel_pair **tmp2; if (!(tmp2 = ast_realloc(mixing_array->chan_pairs, @@ -1315,7 +1320,6 @@ static int softmix_mixing_array_grow(struct softmix_mixing_array *mixing_array, } mixing_array->chan_pairs = tmp2; } - mixing_array->buffers = tmp; return 0; } diff --git a/configs/samples/queues.conf.sample b/configs/samples/queues.conf.sample index 3e7cbd809..226a3a9ef 100644 --- a/configs/samples/queues.conf.sample +++ b/configs/samples/queues.conf.sample @@ -551,7 +551,7 @@ monitor-type = MixMonitor ; must also preload pbx_config.so and chan_local.so (or pbx_ael.so, pbx_lua.so, ; or pbx_realtime.so, depending on how your dialplan is configured). ; -; syntax: member => interface,[,penalty][,membername][,state_interface][,ringinuse] +; syntax: member => interface,[,penalty][,membername][,state_interface][,ringinuse][,wrapuptime] ; ;member => DAHDI/1 ;member => DAHDI/2,10 diff --git a/contrib/ast-db-manage/config/versions/e2f04d309071_add_wrapuptime_to_queue_members.py b/contrib/ast-db-manage/config/versions/e2f04d309071_add_wrapuptime_to_queue_members.py new file mode 100644 index 000000000..fdb1416cb --- /dev/null +++ b/contrib/ast-db-manage/config/versions/e2f04d309071_add_wrapuptime_to_queue_members.py @@ -0,0 +1,22 @@ +"""add wrapuptime to queue_members + +Revision ID: e2f04d309071 +Revises: 041c0d3d1857 +Create Date: 2017-12-07 08:32:45.360857 + +""" + +# revision identifiers, used by Alembic. +revision = 'e2f04d309071' +down_revision = '041c0d3d1857' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.add_column('queue_members', sa.Column('wrapuptime', sa.Integer)) + + +def downgrade(): + op.drop_column('queue_members', 'wrapuptime') diff --git a/funcs/func_callerid.c b/funcs/func_callerid.c index 527babb93..0b6ab517c 100644 --- a/funcs/func_callerid.c +++ b/funcs/func_callerid.c @@ -978,7 +978,7 @@ static int callerpres_write(struct ast_channel *chan, const char *cmd, char *dat static int callerid_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { char *parms; - struct ast_party_members member; + struct ast_party_members member = { 0, }; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(member); /*!< Member name */ AST_APP_ARG(cid); /*!< Optional caller id to parse instead of from the channel. */ @@ -1135,8 +1135,8 @@ static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, enum ID_FIELD_STATUS status; char *val; char *parms; - struct ast_party_func_args args; - struct ast_party_members member; + struct ast_party_func_args args = { 0, }; + struct ast_party_members member = { 0, }; if (!value || !chan) { return -1; @@ -1291,7 +1291,7 @@ static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, */ static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { - struct ast_party_members member; + struct ast_party_members member = { 0, }; char *read_what; enum ID_FIELD_STATUS status; @@ -1359,8 +1359,8 @@ static int connectedline_write(struct ast_channel *chan, const char *cmd, char * char *val; char *parms; void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update); - struct ast_party_func_args args; - struct ast_party_members member; + struct ast_party_func_args args = { 0, }; + struct ast_party_members member = { 0, }; struct ast_flags opts; char *opt_args[CONNECTED_LINE_OPT_ARG_ARRAY_SIZE]; enum ID_FIELD_STATUS status; @@ -1464,7 +1464,7 @@ static int connectedline_write(struct ast_channel *chan, const char *cmd, char * */ static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { - struct ast_party_members member; + struct ast_party_members member = { 0, }; char *read_what; const struct ast_party_redirecting *ast_redirecting; enum ID_FIELD_STATUS status; @@ -1601,8 +1601,8 @@ static int redirecting_write(struct ast_channel *chan, const char *cmd, char *da char *val; char *parms; void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update); - struct ast_party_func_args args; - struct ast_party_members member; + struct ast_party_func_args args = { 0, }; + struct ast_party_members member = { 0, }; struct ast_flags opts; char *opt_args[REDIRECTING_OPT_ARG_ARRAY_SIZE]; diff --git a/main/cel.c b/main/cel.c index cec0a85e4..24a35be7a 100644 --- a/main/cel.c +++ b/main/cel.c @@ -1835,9 +1835,9 @@ void ast_cel_publish_event(struct ast_channel *chan, struct ast_json *cel_blob; struct stasis_message *message; - cel_blob = ast_json_pack("{s: i, s: O}", + cel_blob = ast_json_pack("{s: i, s: o}", "event_type", event_type, - "event_details", blob); + "event_details", ast_json_ref(blob)); message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), cel_generic_type(), cel_blob); if (message) { diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 68c53e7ff..a2c0770d3 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -3092,10 +3092,10 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg, const struct stasis_message_sanitizer *sanitize) { struct rtcp_message_payload *payload = stasis_message_data(msg); - RAII_VAR(struct ast_json *, json_rtcp_report, NULL, ast_json_unref); - RAII_VAR(struct ast_json *, json_rtcp_report_blocks, NULL, ast_json_unref); - RAII_VAR(struct ast_json *, json_rtcp_sender_info, NULL, ast_json_unref); - RAII_VAR(struct ast_json *, json_channel, NULL, ast_json_unref); + struct ast_json *json_rtcp_report = NULL; + struct ast_json *json_rtcp_report_blocks; + struct ast_json *json_rtcp_sender_info = NULL; + struct ast_json *json_channel = NULL; int i; json_rtcp_report_blocks = ast_json_array_create(); @@ -3106,20 +3106,19 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg, for (i = 0; i < payload->report->reception_report_count && payload->report->report_block[i]; i++) { struct ast_json *json_report_block; char str_lsr[32]; + snprintf(str_lsr, sizeof(str_lsr), "%u", payload->report->report_block[i]->lsr); json_report_block = ast_json_pack("{s: i, s: i, s: i, s: i, s: i, s: s, s: i}", - "source_ssrc", payload->report->report_block[i]->source_ssrc, - "fraction_lost", payload->report->report_block[i]->lost_count.fraction, - "packets_lost", payload->report->report_block[i]->lost_count.packets, - "highest_seq_no", payload->report->report_block[i]->highest_seq_no, - "ia_jitter", payload->report->report_block[i]->ia_jitter, - "lsr", str_lsr, - "dlsr", payload->report->report_block[i]->dlsr); - if (!json_report_block) { - return NULL; - } - - if (ast_json_array_append(json_rtcp_report_blocks, json_report_block)) { + "source_ssrc", payload->report->report_block[i]->source_ssrc, + "fraction_lost", payload->report->report_block[i]->lost_count.fraction, + "packets_lost", payload->report->report_block[i]->lost_count.packets, + "highest_seq_no", payload->report->report_block[i]->highest_seq_no, + "ia_jitter", payload->report->report_block[i]->ia_jitter, + "lsr", str_lsr, + "dlsr", payload->report->report_block[i]->dlsr); + if (!json_report_block + || ast_json_array_append(json_rtcp_report_blocks, json_report_block)) { + ast_json_unref(json_rtcp_report_blocks); return NULL; } } @@ -3127,25 +3126,27 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg, if (payload->report->type == AST_RTP_RTCP_SR) { char sec[32]; char usec[32]; + snprintf(sec, sizeof(sec), "%lu", (unsigned long)payload->report->sender_information.ntp_timestamp.tv_sec); snprintf(usec, sizeof(usec), "%lu", (unsigned long)payload->report->sender_information.ntp_timestamp.tv_usec); json_rtcp_sender_info = ast_json_pack("{s: s, s: s, s: i, s: i, s: i}", - "ntp_timestamp_sec", sec, - "ntp_timestamp_usec", usec, - "rtp_timestamp", payload->report->sender_information.rtp_timestamp, - "packets", payload->report->sender_information.packet_count, - "octets", payload->report->sender_information.octet_count); + "ntp_timestamp_sec", sec, + "ntp_timestamp_usec", usec, + "rtp_timestamp", payload->report->sender_information.rtp_timestamp, + "packets", payload->report->sender_information.packet_count, + "octets", payload->report->sender_information.octet_count); if (!json_rtcp_sender_info) { + ast_json_unref(json_rtcp_report_blocks); return NULL; } } json_rtcp_report = ast_json_pack("{s: i, s: i, s: i, s: o, s: o}", - "ssrc", payload->report->ssrc, - "type", payload->report->type, - "report_count", payload->report->reception_report_count, - "sender_information", json_rtcp_sender_info ? ast_json_ref(json_rtcp_sender_info) : ast_json_ref(ast_json_null()), - "report_blocks", ast_json_ref(json_rtcp_report_blocks)); + "ssrc", payload->report->ssrc, + "type", payload->report->type, + "report_count", payload->report->reception_report_count, + "sender_information", json_rtcp_sender_info ?: ast_json_null(), + "report_blocks", json_rtcp_report_blocks); if (!json_rtcp_report) { return NULL; } @@ -3153,14 +3154,15 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg, if (payload->snapshot) { json_channel = ast_channel_snapshot_to_json(payload->snapshot, sanitize); if (!json_channel) { + ast_json_unref(json_rtcp_report); return NULL; } } return ast_json_pack("{s: o, s: o, s: o}", - "channel", payload->snapshot ? ast_json_ref(json_channel) : ast_json_ref(ast_json_null()), - "rtcp_report", ast_json_ref(json_rtcp_report), - "blob", ast_json_deep_copy(payload->blob)); + "channel", payload->snapshot ? json_channel : ast_json_null(), + "rtcp_report", json_rtcp_report, + "blob", ast_json_deep_copy(payload->blob) ?: ast_json_null()); } static void rtp_rtcp_report_dtor(void *obj) |