diff --git a/apps/app_dial.c b/apps/app_dial.c index 21d37ebacc9ba1c915ae30263f2be02a73056fd1..4adfc47ecf3ef7e968f733dccecd66f5e57bac76 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -565,9 +565,27 @@ <variable name="DIALEDTIME"> <para>This is the time from dialing a channel until when it is disconnected.</para> </variable> + <variable name="DIALEDTIME_MS"> + <para>This is the milliseconds version of the DIALEDTIME variable.</para> + </variable> <variable name="ANSWEREDTIME"> <para>This is the amount of time for actual call.</para> </variable> + <variable name="ANSWEREDTIME_MS"> + <para>This is the milliseconds version of the ANSWEREDTIME variable.</para> + </variable> + <variable name="RINGTIME"> + <para>This is the time from creating the channel to the first RINGING event received. Empty if there was no ring.</para> + </variable> + <variable name="RINGTIME_MS"> + <para>This is the milliseconds version of the RINGTIME variable.</para> + </variable> + <variable name="PROGRESSTIME"> + <para>This is the time from creating the channel to the first PROGRESS event received. Empty if there was no such event.</para> + </variable> + <variable name="PROGRESSTIME_MS"> + <para>This is the milliseconds version of the PROGRESSTIME variable.</para> + </variable> <variable name="DIALEDPEERNAME"> <para>The name of the outbound channel that answered the call.</para> </variable> @@ -1162,6 +1180,23 @@ static void update_connected_line_from_peer(struct ast_channel *chan, struct ast ast_party_connected_line_free(&connected_caller); } +/*! + * \internal + * \pre chan is locked + */ +static void set_duration_var(struct ast_channel *chan, const char *var_base, int64_t duration) +{ + char buf[32]; + char full_var_name[128]; + + snprintf(buf, sizeof(buf), "%" PRId64, duration / 1000); + pbx_builtin_setvar_helper(chan, var_base, buf); + + snprintf(full_var_name, sizeof(full_var_name), "%s_MS", var_base); + snprintf(buf, sizeof(buf), "%" PRId64, duration); + pbx_builtin_setvar_helper(chan, full_var_name, buf); +} + static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_head *out_chans, int *to, struct ast_flags64 *peerflags, char *opt_args[], @@ -1184,6 +1219,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, int is_cc_recall; int cc_frame_received = 0; int num_ringing = 0; + int sent_ring = 0; + int sent_progress = 0; struct timeval start = ast_tvnow(); if (single) { @@ -1457,6 +1494,23 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, ast_indicate(in, AST_CONTROL_RINGING); pa->sentringing++; } + if (!sent_ring) { + struct timeval now, then; + int64_t diff; + + now = ast_tvnow(); + + ast_channel_lock(in); + ast_channel_stage_snapshot(in); + + then = ast_channel_creationtime(c); + diff = ast_tvzero(then) ? 0 : ast_tvdiff_ms(now, then); + set_duration_var(in, "RINGTIME", diff); + + ast_channel_stage_snapshot_done(in); + ast_channel_unlock(in); + sent_ring = 1; + } } ast_channel_publish_dial(in, c, NULL, "RINGING"); break; @@ -1472,6 +1526,23 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, ast_indicate(in, AST_CONTROL_PROGRESS); } } + if (!sent_progress) { + struct timeval now, then; + int64_t diff; + + now = ast_tvnow(); + + ast_channel_lock(in); + ast_channel_stage_snapshot(in); + + then = ast_channel_creationtime(c); + diff = ast_tvzero(then) ? 0 : ast_tvdiff_ms(now, then); + set_duration_var(in, "PROGRESSTIME", diff); + + ast_channel_stage_snapshot_done(in); + ast_channel_unlock(in); + sent_progress = 1; + } if (!ast_strlen_zero(dtmf_progress)) { ast_verb(3, "Sending DTMF '%s' to the called party as result of receiving a PROGRESS message.\n", @@ -2058,18 +2129,12 @@ static int setup_privacy_args(struct privacy_args *pa, static void end_bridge_callback(void *data) { - char buf[80]; - time_t end; struct ast_channel *chan = data; - time(&end); - ast_channel_lock(chan); ast_channel_stage_snapshot(chan); - snprintf(buf, sizeof(buf), "%d", ast_channel_get_up_time(chan)); - pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); - snprintf(buf, sizeof(buf), "%d", ast_channel_get_duration(chan)); - pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); + set_duration_var(chan, "ANSWEREDTIME", ast_channel_get_up_time_ms(chan)); + set_duration_var(chan, "DIALEDTIME", ast_channel_get_duration_ms(chan)); ast_channel_stage_snapshot_done(chan); ast_channel_unlock(chan); } @@ -2211,7 +2276,13 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", ""); pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ""); pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", ""); + pbx_builtin_setvar_helper(chan, "ANSWEREDTIME_MS", ""); pbx_builtin_setvar_helper(chan, "DIALEDTIME", ""); + pbx_builtin_setvar_helper(chan, "DIALEDTIME_MS", ""); + pbx_builtin_setvar_helper(chan, "RINGTIME", ""); + pbx_builtin_setvar_helper(chan, "RINGTIME_MS", ""); + pbx_builtin_setvar_helper(chan, "PROGRESSTIME", ""); + pbx_builtin_setvar_helper(chan, "PROGRESSTIME_MS", ""); ast_channel_stage_snapshot_done(chan); max_forwards = ast_max_forwards_get(chan); ast_channel_unlock(chan); diff --git a/doc/CHANGES-staging/app_dial_ringtime_progresstime.txt b/doc/CHANGES-staging/app_dial_ringtime_progresstime.txt new file mode 100644 index 0000000000000000000000000000000000000000..9b5cdd508919ee686a9a87dd38ebbe8db9aaeac6 --- /dev/null +++ b/doc/CHANGES-staging/app_dial_ringtime_progresstime.txt @@ -0,0 +1,12 @@ +Subject: Dial + +Add RINGTIME and RINGTIME_MS variables containing respectively seconds and +milliseconds between creation of the dialing channel and receiving the first +RINGING signal + +Add PROGRESSTIME and PROGRESSTIME_MS variables analogous to the above with respect to +the PROGRESS signal. Shorter of these two times should be equivalent to +the PDD (Post Dial Delay) value + +Add DIALEDTIME_MS and ANSWEREDTIME_MS variables to get millisecond resolution +versions of DIALEDTIME and ANSWEREDTIME diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index e2f79592d79f9d7e8d81c801d678f9fce672011d..3d8b70a8cec08fe39e8fee9f9802fbb24038acae 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -2414,6 +2414,18 @@ int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, /*! Deactivate an active generator */ void ast_deactivate_generator(struct ast_channel *chan); +/*! + * \since 13.27.0 + * \since 16.4.0 + * \brief Obtain how long it's been, in milliseconds, since the channel was created + * + * \param chan The channel object + * + * \retval 0 if the time value cannot be computed (or you called this really fast) + * \retval The number of milliseconds since channel creation + */ +int64_t ast_channel_get_duration_ms(struct ast_channel *chan); + /*! * \since 12 * \brief Obtain how long the channel since the channel was created @@ -2425,6 +2437,18 @@ void ast_deactivate_generator(struct ast_channel *chan); */ int ast_channel_get_duration(struct ast_channel *chan); +/*! + * \since 13.27.0 + * \since 16.4.0 + * \brief Obtain how long it has been since the channel was answered in ms + * + * \param chan The channel object + * + * \retval 0 if the channel isn't answered (or you called this really fast) + * \retval The number of milliseconds the channel has been up + */ +int64_t ast_channel_get_up_time_ms(struct ast_channel *chan); + /*! * \since 12 * \brief Obtain how long it has been since the channel was answered diff --git a/main/channel.c b/main/channel.c index bad14800cd87a0267c26ebc04dd3bef67a7396d9..be88a3b33f73029cc464dde12b8ddfffa32f4243 100644 --- a/main/channel.c +++ b/main/channel.c @@ -2789,24 +2789,34 @@ inline int ast_auto_answer(struct ast_channel *chan) return ast_answer(chan); } -int ast_channel_get_duration(struct ast_channel *chan) +int64_t ast_channel_get_duration_ms(struct ast_channel *chan) { ast_assert(NULL != chan); if (ast_tvzero(ast_channel_creationtime(chan))) { return 0; } - return (ast_tvdiff_ms(ast_tvnow(), ast_channel_creationtime(chan)) / 1000); + return ast_tvdiff_ms(ast_tvnow(), ast_channel_creationtime(chan)); } -int ast_channel_get_up_time(struct ast_channel *chan) +int ast_channel_get_duration(struct ast_channel *chan) +{ + return (ast_channel_get_duration_ms(chan) / 1000); +} + +int64_t ast_channel_get_up_time_ms(struct ast_channel *chan) { ast_assert(NULL != chan); if (ast_tvzero(ast_channel_answertime(chan))) { return 0; } - return (ast_tvdiff_ms(ast_tvnow(), ast_channel_answertime(chan)) / 1000); + return ast_tvdiff_ms(ast_tvnow(), ast_channel_answertime(chan)); +} + +int ast_channel_get_up_time(struct ast_channel *chan) +{ + return (ast_channel_get_up_time_ms(chan) / 1000); } static void deactivate_generator_nolock(struct ast_channel *chan)