From 1d09a7e9f51e0a3f3034d308521fb1157796e04a Mon Sep 17 00:00:00 2001 From: z3bra Date: Mon, 21 Nov 2016 13:52:59 +0100 Subject: Make sure call is only canceled once Upon receiving a FINISHED state, the client should consider the call over, and free its local variable. It should NOT try to send a CANCEL signal, as it could try to cancel the call twice, resulting in a double free() that can crash the core. --- ratox.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/ratox.c b/ratox.c index 55da416..48631a9 100644 --- a/ratox.c +++ b/ratox.c @@ -383,6 +383,7 @@ cbcallstate(ToxAV *av, uint32_t fnum, uint32_t state, void *udata) if ((state & TOXAV_FRIEND_CALL_STATE_ERROR) || (state & TOXAV_FRIEND_CALL_STATE_FINISHED)) { + f->av.state &= ~TRANSMITTING; cancelcall(f, "Finished"); return; } @@ -391,12 +392,23 @@ cbcallstate(ToxAV *av, uint32_t fnum, uint32_t state, void *udata) * As long as we receive a state callback, it means the peer * accepted the call */ - f->av.state |= TRANSMITTING; + if (f->av.state & RINGING) { + f->av.n = 0; + f->av.lastsent.tv_sec = 0; + f->av.lastsent.tv_nsec = 0; + + f->av.frame = malloc(sizeof(int16_t) * framesize); + if (!f->av.frame) + eprintf("malloc:"); + + f->av.state &= ~RINGING; + f->av.state |= TRANSMITTING; + } /* let us start sending audio */ if (state & TOXAV_FRIEND_CALL_STATE_ACCEPTING_A) { f->av.state |= OUTGOING; - logmsg(": %s : Audio > Started/Resumed\n", f->name); + logmsg(": %s : Audio > Started\n", f->name); } } @@ -477,6 +489,9 @@ sendfriendcalldata(struct friend *f) ssize_t n; TOXAV_ERR_SEND_FRAME err; + if (!f->av.state) + return; + n = fiforead(f->dirfd, &f->fd[FCALL_IN], ffiles[FCALL_IN], f->av.frame + (f->av.state & INCOMPLETE) * f->av.n, framesize * sizeof(int16_t) - (f->av.state & INCOMPLETE) * f->av.n); @@ -494,10 +509,6 @@ sendfriendcalldata(struct friend *f) return; } - /* discard data if friend doesn't accept audio */ - if (!(f->av.state & OUTGOING)) - return; - clock_gettime(CLOCK_MONOTONIC, &now); diff = timediff(f->av.lastsent, now); if (diff.tv_sec == 0 && diff.tv_nsec < (AUDIOFRAME - 1) * 1E6) { @@ -1672,10 +1683,10 @@ loop(void) } if (f->av.state & TRANSMITTING) { - if ((f->av.state & INCOMING) || (f->av.state & OUTGOING)) - continue; - cancelcall(f, "Hanged up"); - } else { + if (!(f->av.state & INCOMING) && !(f->av.state & OUTGOING)) + cancelcall(f, "Hanged up"); + } + if (f->av.state & RINGING) { if (!(f->av.state & INCOMING)) continue; if (!toxav_answer(toxav, f->num, AUDIOBITRATE, 0, NULL)) { @@ -1759,13 +1770,7 @@ loop(void) fiforeset(f->dirfd, &f->fd[FCALL_IN], ffiles[FCALL_IN]); break; } - f->av.n = 0; - f->av.lastsent.tv_sec = 0; - f->av.lastsent.tv_nsec = 0; - f->av.state |= OUTGOING; - f->av.frame = malloc(sizeof(int16_t) * framesize); - if (!f->av.frame) - eprintf("malloc:"); + f->av.state |= RINGING; logmsg(": %s : Audio : Tx > Inviting\n", f->name); } else { if (f->av.state & OUTGOING) -- cgit v1.2.3