commit 1d09a7e9f51e0a3f3034d308521fb1157796e04a
parent e9f47ae7f10d1b05dc56004e442e239fcbecd6a2
Author: z3bra <contactatz3bradotorg>
Date: Mon, 21 Nov 2016 13:52:59 +0100
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.
Diffstat:
M | ratox.c | | | 39 | ++++++++++++++++++++++----------------- |
1 file changed, 22 insertions(+), 17 deletions(-)
diff --git 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)