[Asterisk-code-review] jitterbuffer: Correct signed/unsigned mismatch causing assert (asterisk[16])
George Joseph
asteriskteam at digium.com
Thu Jun 17 08:11:07 CDT 2021
George Joseph has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/16073 )
Change subject: jitterbuffer: Correct signed/unsigned mismatch causing assert
......................................................................
jitterbuffer: Correct signed/unsigned mismatch causing assert
If the system time slews backwards because of a time adjustment
between the time a frame is timestamped and the time we check the
timestamps in abstract_jb:hook_event_cb(), we get a negative
interval, but we don't check for that there.
abstract_jb:hook_event_cb() then calls fixedjitterbuffer:fixed_jb_get
() (via abstract_jb:jb_get_fixed) and the first thing that does is
assert(interval >= 0).
There are several issues with this...
* abstract_jb:hook_event_cb() saves the interval in a variable
named "now" which is confusing in itself.
* "now" is defined as an unsigned int which converts the negative
value returned from ast_tvdiff_ms() to a large positive value.
* fixed_jb_get()'s parameter is defined as a signed int so the
interval gets converted back to a negative value.
* fixed_jb_get()'s assert is NOT an ast_assert but a direct define
that points to the system assert() so it triggers even in
production mode.
So...
* hook_event_cb()'s "now" was renamed to "relative_frame_start" and
changed to an int64_t.
* hook_event_cb() now checks for a negative value right after
retrieving both the current and framedata timestamps and just
returns the frame if the difference is negative.
* fixed_jb_get()'s local define of ASSERT() was changed to call
ast_assert() instead of the system assert().
ASTERISK-29480
Reported by: Dan Cropp
Change-Id: Ic469dec73c2edc3ba134cda6721a999a9714f3c9
---
M main/abstract_jb.c
M main/fixedjitterbuf.c
2 files changed, 19 insertions(+), 9 deletions(-)
git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/73/16073/1
diff --git a/main/abstract_jb.c b/main/abstract_jb.c
index 7549008..b0f995b 100644
--- a/main/abstract_jb.c
+++ b/main/abstract_jb.c
@@ -954,7 +954,7 @@
{
struct jb_framedata *framedata = data;
struct timeval now_tv;
- unsigned long now;
+ int64_t relative_frame_start;
int putframe = 0; /* signifies if audio frame was placed into the buffer or not */
switch (event) {
@@ -1064,7 +1064,17 @@
}
now_tv = ast_tvnow();
- now = ast_tvdiff_ms(now_tv, framedata->start_tv);
+ relative_frame_start = ast_tvdiff_ms(now_tv, framedata->start_tv);
+ if (relative_frame_start < 0) {
+ /*
+ * The only way for this to happen is if the system time has
+ * slewed backwards between the time framedata->start_tv was
+ * set and now. Think an ntpd or systemd-timesyncd adjustment.
+ *
+ * Just pass the frame through.
+ */
+ return frame;
+ }
if (frame->frametype == AST_FRAME_VOICE) {
int res;
@@ -1084,9 +1094,9 @@
}
if (!framedata->first) {
framedata->first = 1;
- res = framedata->jb_impl->put_first(framedata->jb_obj, jbframe, now);
+ res = framedata->jb_impl->put_first(framedata->jb_obj, jbframe, relative_frame_start);
} else {
- res = framedata->jb_impl->put(framedata->jb_obj, jbframe, now);
+ res = framedata->jb_impl->put(framedata->jb_obj, jbframe, relative_frame_start);
}
if (res == AST_JB_IMPL_OK) {
@@ -1104,7 +1114,7 @@
int res;
long next = framedata->jb_impl->next(framedata->jb_obj);
- /* If now is earlier than the next expected output frame
+ /* If relative_frame_start is earlier than the next expected output frame
* from the jitterbuffer we may choose to pass on retrieving
* a frame during this read iteration. The only exception
* to this rule is when an audio frame is placed into the buffer
@@ -1113,8 +1123,8 @@
* doing this we are able to feed off the timing of the input frames
* and only rely on our jitterbuffer timer when frames are dropped.
* During testing, this hybrid form of timing gave more reliable results. */
- if (now < next) {
- long int diff = next - now;
+ if (relative_frame_start < next) {
+ long int diff = next - relative_frame_start;
if (!putframe) {
return frame;
} else if (diff >= framedata->timer_interval) {
@@ -1124,7 +1134,7 @@
ast_frfree(frame);
frame = &ast_null_frame;
- res = framedata->jb_impl->get(framedata->jb_obj, &frame, now, framedata->timer_interval);
+ res = framedata->jb_impl->get(framedata->jb_obj, &frame, relative_frame_start, framedata->timer_interval);
switch (res) {
case AST_JB_IMPL_OK:
/* got it, and pass it through */
diff --git a/main/fixedjitterbuf.c b/main/fixedjitterbuf.c
index 3c350b4..6c92329 100644
--- a/main/fixedjitterbuf.c
+++ b/main/fixedjitterbuf.c
@@ -41,7 +41,7 @@
#ifdef FIXED_JB_DEBUG
#define ASSERT(a)
#else
-#define ASSERT(a) assert(a)
+#define ASSERT(a) ast_assert(a)
#endif
/*! \brief private fixed_jb structure */
--
To view, visit https://gerrit.asterisk.org/c/asterisk/+/16073
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings
Gerrit-Project: asterisk
Gerrit-Branch: 16
Gerrit-Change-Id: Ic469dec73c2edc3ba134cda6721a999a9714f3c9
Gerrit-Change-Number: 16073
Gerrit-PatchSet: 1
Gerrit-Owner: George Joseph <gjoseph at digium.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20210617/c6d1c69d/attachment.html>
More information about the asterisk-code-review
mailing list