commit 91cf7e937b43cd56e45699e2f1c73f109c16e0b6
parent 2fe183edfe6273cdf1a1f0c3c1cf8a638b823caf
Author: FRIGN <dev@frign.de>
Date: Mon, 13 Oct 2014 19:09:35 +0200
Fortify error-checks and FSM
Basically the direct calls to cancelcall() should be minimized
and only set off in a callback.
Additionally, tweak other error-cases and don't always quit fatally
but instead provide ways to get out of an error-condition.
Diffstat:
M | ratox.c | | | 95 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
1 file changed, 60 insertions(+), 35 deletions(-)
diff --git a/ratox.c b/ratox.c
@@ -367,6 +367,9 @@ cbcallinvite(void *av, int32_t cnum, void *udata)
fnum = toxav_get_peer_id(toxav, cnum, 0);
if (fnum < 0) {
weprintf("Failed to determine peer-id from call-id\n");
+ r = toxav_reject(toxav, cnum, NULL);
+ if (r < 0)
+ weprintf("Failed to reject call\n");
return;
}
TAILQ_FOREACH(f, &friendhead, entry)
@@ -379,6 +382,9 @@ cbcallinvite(void *av, int32_t cnum, void *udata)
r = toxav_get_peer_csettings(toxav, cnum, 0, &avconfig);
if (r < 0) {
weprintf("Failed to determine peer call type\n");
+ r = toxav_reject(toxav, f->av.num, NULL);
+ if (r < 0)
+ weprintf("Failed to reject call\n");
return;
}
@@ -413,10 +419,12 @@ cbcallstart(void *av, int32_t cnum, void *type)
if(!strncmp(type, "Tx", 2))
preparetxcall(f);
- r = toxav_prepare_transmission(toxav, cnum, av_jbufdc, av_VADd, 0);
+ r = toxav_prepare_transmission(toxav, f->av.num, av_jbufdc, av_VADd, 0);
if (r < 0) {
weprintf("Failed to prepare %s AV transmission\n", type);
- cancelcall(f, "Failed");
+ r = toxav_hangup(toxav, f->av.num);
+ if (r < 0)
+ weprintf("Failed to hang up\n");
return;
}
logmsg(": %s : %s AV > Started\n", f->name, type);
@@ -490,13 +498,15 @@ cancelcall(struct friend *f, char *action)
logmsg(": %s : Rx/Tx AV > %s\n", f->name, action);
if (f->av.num != -1) {
- r = toxav_kill_transmission(toxav, f->av.num);
- if (r < 0)
- weprintf("Failed to kill transmission\n");
+ if (toxav_get_call_state(toxav, f->av.num) != av_CallInviting) {
+ r = toxav_kill_transmission(toxav, f->av.num);
+ if (r < 0)
+ weprintf("Failed to kill transmission\n");
+ }
}
f->av.num = -1;
- /* Cancel Tx side of the call */
+ /* Cancel Rx side of the call */
if (f->fd[FCALL_OUT] != -1) {
close(f->fd[FCALL_OUT]);
f->fd[FCALL_OUT] = -1;
@@ -505,7 +515,7 @@ cancelcall(struct friend *f, char *action)
lseek(f->fd[FCALL_PENDING], 0, SEEK_SET);
dprintf(f->fd[FCALL_PENDING], "0\n");
- /* Cancel Rx side of the call */
+ /* Cancel Tx side of the call */
free(f->av.frame);
f->av.frame = NULL;
fiforeset(f->dirfd, &f->fd[FCALL_IN], ffiles[FCALL_IN]);
@@ -542,8 +552,10 @@ sendfriendcalldata(struct friend *f)
payloadsize = toxav_prepare_audio_frame(toxav, f->av.num,
f->av.payload, sizeof(f->av.payload),
(int16_t *)f->av.frame, framesize);
- if (payloadsize < 0)
- eprintf("Failed to encode payload\n");
+ if (payloadsize < 0) {
+ weprintf("Failed to encode payload\n");
+ return;
+ }
clock_gettime(CLOCK_MONOTONIC, &now);
diff = timediff(f->av.lastsent, now);
@@ -554,7 +566,7 @@ sendfriendcalldata(struct friend *f)
clock_gettime(CLOCK_MONOTONIC, &f->av.lastsent);
r = toxav_send_audio(toxav, f->av.num, f->av.payload, payloadsize);
if (r < 0)
- eprintf("Failed to send audio frame\n");
+ weprintf("Failed to send audio frame\n");
}
static void
@@ -566,9 +578,10 @@ cbconnstatus(Tox *m, int32_t frnum, uint8_t status, void *udata)
int r;
r = tox_get_name(tox, frnum, (uint8_t *)name);
- if (r < 0)
- eprintf("Failed to get name for friend number %ld\n",
- (long)frnum);
+ if (r < 0) {
+ weprintf("Failed to get name for friend number %ld\n", (long)frnum);
+ return;
+ }
if (r == 0)
snprintf(name, sizeof(name), "Anonymous");
@@ -965,8 +978,10 @@ readpass(const char *prompt)
char pass[BUFSIZ], *p;
p = readpassphrase(prompt, pass, sizeof(pass), RPP_ECHO_OFF);
- if (!p)
- eprintf("readpassphrase:");
+ if (!p) {
+ weprintf("readpassphrase:");
+ return -1;
+ }
if (p[0] == '\0')
return -1;
passphrase = realloc(passphrase, strlen(p)); /* not null-terminated */
@@ -994,8 +1009,10 @@ dataload(void)
sz = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
- if (sz == 0)
- eprintf("Data : %s > Empty\n", DATAFILE);
+ if (sz == 0) {
+ weprintf("Data : %s > Empty\n", DATAFILE);
+ return;
+ }
data = malloc(sz);
if (!data)
@@ -1095,29 +1112,31 @@ localinit(void)
/* Dump current name */
r = tox_get_self_name(tox, name);
- if (r == 0)
+ if (r == 0) {
weprintf("Failed to get current name\n");
- if (r > sizeof(name) - 1)
+ } else if (r > sizeof(name) - 1) {
r = sizeof(name) - 1;
+ }
name[r] = '\0';
ftruncate(gslots[NAME].fd[OUT], 0);
dprintf(gslots[NAME].fd[OUT], "%s\n", name);
/* Dump status */
r = tox_get_self_status_message(tox, status, sizeof(status) - 1);
- if (r == 0)
+ if (r == 0) {
weprintf("Failed to get current status\n");
- if (r > sizeof(status) - 1)
+ } else if (r > sizeof(status) - 1) {
r = sizeof(status) - 1;
+ }
status[r] = '\0';
ftruncate(gslots[STATUS].fd[OUT], 0);
dprintf(gslots[STATUS].fd[OUT], "%s\n", status);
/* Dump user state */
r = tox_get_self_user_status(tox);
- if (r < 0)
+ if (r < 0) {
weprintf("Failed to get current state\n");
- if (r >= LEN(ustate)) {
+ } else if (r >= LEN(ustate)) {
ftruncate(gslots[STATE].fd[ERR], 0);
dprintf(gslots[STATE].fd[ERR], "invalid\n");
weprintf("Invalid user state: %d\n", r);
@@ -1259,9 +1278,10 @@ friendcreate(int32_t frnum)
eprintf("calloc:");
r = tox_get_name(tox, frnum, (uint8_t *)f->name);
- if (r < 0)
- eprintf("Failed to get name for friend number %ld\n",
- (long)frnum);
+ if (r < 0) {
+ weprintf("Failed to get name for friend number %ld\n", (long)frnum);
+ return NULL;
+ }
if (r == 0)
snprintf(f->name, sizeof(f->name), "Anonymous");
else
@@ -1307,19 +1327,21 @@ friendcreate(int32_t frnum)
/* Dump status */
r = tox_get_status_message(tox, frnum, status, sizeof(status) - 1);
- if (r < 0 )
+ if (r < 0) {
weprintf("Failed to get user status\n");
- if (r > sizeof(status) - 1)
+ r = 0;
+ } else if (r > sizeof(status) - 1) {
r = sizeof(status) - 1;
+ }
status[r] = '\0';
ftruncate(f->fd[FSTATUS], 0);
dprintf(f->fd[FSTATUS], "%s\n", status);
/* Dump user state */
r = tox_get_user_status(tox, frnum);
- if (r < 0)
+ if (r < 0) {
weprintf("Failed to get user state\n");
- if (r >= LEN(ustate)) {
+ } else if (r >= LEN(ustate)) {
weprintf("Invalid user state: %d\n", r);
} else {
ftruncate(f->fd[FSTATE], 0);
@@ -1348,7 +1370,7 @@ frienddestroy(struct friend *f)
canceltxtransfer(f);
cancelrxtransfer(f);
if (f->av.num != -1 && toxav_get_call_state(toxav, f->av.num) != av_CallNonExistant)
- cancelcall(f, "Destroying");
+ cancelcall(f, "Destroying"); /* todo: check state */
for (i = 0; i < LEN(ffiles); i++) {
if (f->dirfd != -1) {
unlinkat(f->dirfd, ffiles[i].name, 0);
@@ -1733,7 +1755,9 @@ loop(void)
r = toxav_answer(toxav, f->av.num, &toxavconfig);
if (r < 0) {
weprintf("Failed to answer call\n");
- cancelcall(f, "Failed");
+ r = toxav_reject(toxav, f->av.num, NULL);
+ if (r < 0)
+ weprintf("Failed to reject call\n");
}
break;
case av_CallActive:
@@ -1777,7 +1801,8 @@ loop(void)
r = tox_add_friend_norequest(tox, req->id);
if (r < 0) {
weprintf("Failed to add friend %s\n", req->idstr);
- goto cleanup;
+ fiforeset(gslots[REQUEST].fd[OUT], &req->fd, reqfifo);
+ continue;
}
if (c == '1') {
friendcreate(r);
@@ -1787,7 +1812,6 @@ loop(void)
tox_del_friend(tox, r);
logmsg("Request : %s > Rejected\n", req->idstr);
}
-cleanup:
unlinkat(gslots[REQUEST].fd[OUT], req->idstr, 0);
close(req->fd);
TAILQ_REMOVE(&reqhead, req, entry);
@@ -1825,7 +1849,8 @@ cleanup:
r = toxav_call(toxav, &f->av.num, f->num, &toxavconfig, RINGINGDELAY);
if (r < 0) {
weprintf("Failed to call\n");
- cancelcall(f, "Failed");
+ fiforeset(f->dirfd, &f->fd[FCALL_IN], ffiles[FCALL_IN]);
+ break;
}
logmsg(": %s : Tx AV > Inviting\n", f->name);
break;