From 91cf7e937b43cd56e45699e2f1c73f109c16e0b6 Mon Sep 17 00:00:00 2001 From: FRIGN Date: Mon, 13 Oct 2014 19:09:35 +0200 Subject: 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. --- ratox.c | 95 +++++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 35 deletions(-) diff --git a/ratox.c b/ratox.c index ff686f9..4e14c72 100644 --- 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; -- cgit v1.2.3