URI: 
       tFortify and optimize file-sending - ratox - FIFO based tox client
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 11ddb1aacdf44d8517480a030db425181952b777
   DIR parent 9e1d2b5522bfb88474570ffebd6546f2d4bf445f
  HTML Author: FRIGN <dev@frign.de>
       Date:   Tue, 14 Oct 2014 18:48:22 +0200
       
       Fortify and optimize file-sending
       
       Do this in two ways:
       
       1) only allow ratox to stay in the file-sender for a certain amount
       of time
       2) Stop hammering tox_file_send_data(). When it returns -1, we put
       tthe given friend into a cooldown-state, because all internal transmission
       slots are full.
       
       File sending thus now works in bursts, reading from file_in as long
       as tox_do() allows or until tox_file_send_data() fails.
       
       An easy way to see why we need to do the former is piping /dev/urandom
       tto file_in, which never blocks. Effectively, the user goes "offline"
       after a while given he is trapped inside the loop.
       
       Piping to /dev/urandom is not an unrealistic testcase. Imagine a
       researcher who desperately needs true random data from his special
       RNG in his lab using ratox and piping it through /dev/urandom.
       
       Diffstat:
         M ratox.c                             |      39 ++++++++++++++++++++++++++++---
       
       1 file changed, 36 insertions(+), 3 deletions(-)
       ---
   DIR diff --git a/ratox.c b/ratox.c
       t@@ -161,6 +161,8 @@ struct transfer {
                ssize_t n;
                int pendingbuf;
                int state;
       +        struct timespec lastblock;
       +        int cooldown;
        };
        
        struct call {
       t@@ -777,6 +779,9 @@ cbfilecontrol(Tox *m, int32_t frnum, uint8_t rec_sen, uint8_t fnum, uint8_t ctrl
                                f->tx.state = TRANSFER_NONE;
                                free(f->tx.buf);
                                f->tx.buf = NULL;
       +                        f->tx.lastblock.tv_sec = 0;
       +                        f->tx.lastblock.tv_nsec = 0;
       +                        f->tx.cooldown = 0;
                                fiforeset(f->dirfd, &f->fd[FFILE_IN], ffiles[FFILE_IN]);
                        } else {
                                logmsg(": %s : Rx > Cancelled by Sender\n", f->name);
       t@@ -789,6 +794,9 @@ cbfilecontrol(Tox *m, int32_t frnum, uint8_t rec_sen, uint8_t fnum, uint8_t ctrl
                                f->tx.state = TRANSFER_NONE;
                                free(f->tx.buf);
                                f->tx.buf = NULL;
       +                        f->tx.lastblock.tv_sec = 0;
       +                        f->tx.lastblock.tv_nsec = 0;
       +                        f->tx.cooldown = 0;
                        } else {
                                logmsg(": %s : Rx > Complete\n", f->name);
                                if (tox_file_send_control(tox, f->num, 1, 0, TOX_FILECONTROL_FINISHED, NULL, 0) < 0)
       t@@ -882,6 +890,9 @@ canceltxtransfer(struct friend *f)
                f->tx.state = TRANSFER_NONE;
                free(f->tx.buf);
                f->tx.buf = NULL;
       +        f->tx.lastblock.tv_sec = 0;
       +        f->tx.lastblock.tv_nsec = 0;
       +        f->tx.cooldown = 0;
                fiforeset(f->dirfd, &f->fd[FFILE_IN], ffiles[FFILE_IN]);
        }
        
       t@@ -906,8 +917,11 @@ static void
        sendfriendfile(struct friend *f)
        {
                ssize_t n;
       +        struct timespec start, now, diff = {0, 0};
        
       -        while (1) {
       +        clock_gettime(CLOCK_MONOTONIC, &start);
       +
       +        while (diff.tv_sec == 0 && diff.tv_nsec < tox_do_interval(tox) * 1E6) {
                        /* Attempt to transmit the pending buffer */
                        if (f->tx.pendingbuf == 1) {
                                if (tox_file_send_data(tox, f->num, f->tx.fnum, f->tx.buf, f->tx.n) == -1) {
       t@@ -927,14 +941,20 @@ sendfriendfile(struct friend *f)
                                f->tx.state = TRANSFER_NONE;
                                break;
                        }
       -                if (n == -1)
       +                if (n == -1) {
       +                        printf("fiforead in sendfriendfile failed. fix this. errno = %d\n", errno);
                                break;
       +                }
                        /* Store transfer size in case we can't send it right now */
                        f->tx.n = n;
                        if (tox_file_send_data(tox, f->num, f->tx.fnum, f->tx.buf, f->tx.n) == -1) {
       +                        clock_gettime(CLOCK_MONOTONIC, &f->tx.lastblock);
       +                        f->tx.cooldown = 1;
                                f->tx.pendingbuf = 1;
                                return;
                        }
       +                clock_gettime(CLOCK_MONOTONIC, &now);
       +                diff = timediff(start, now);
                }
        }
        
       t@@ -1591,6 +1611,7 @@ loop(void)
                char c;
                fd_set rfds;
                struct timeval tv;
       +        struct timespec curtime, diff;
                struct file reqfifo;
        
                t0 = time(NULL);
       t@@ -1637,13 +1658,25 @@ loop(void)
                        }
        
                        TAILQ_FOREACH(f, &friendhead, entry) {
       +                        /* Check cooldown state of file transfers */
       +                        if (f->tx.cooldown) {
       +                                clock_gettime(CLOCK_MONOTONIC, &curtime);
       +                                diff = timediff(f->tx.lastblock, curtime);
       +
       +                                if (diff.tv_sec > 0 || diff.tv_nsec > tox_do_interval(tox) * 3 * 1E6) {
       +                                        f->tx.lastblock.tv_sec = 0;
       +                                        f->tx.lastblock.tv_nsec = 0;
       +                                        f->tx.cooldown = 0;
       +                                }
       +                        }
       +
                                /* Only monitor friends that are online */
                                if (tox_get_friend_connection_status(tox, f->num) == 1) {
                                        FD_SET(f->fd[FTEXT_IN], &rfds);
                                        if (f->fd[FTEXT_IN] > fdmax)
                                                fdmax = f->fd[FTEXT_IN];
                                        if (f->tx.state == TRANSFER_NONE ||
       -                                    f->tx.state == TRANSFER_INPROGRESS) {
       +                                    (f->tx.state == TRANSFER_INPROGRESS && !f->tx.cooldown)) {
                                                FD_SET(f->fd[FFILE_IN], &rfds);
                                                if (f->fd[FFILE_IN] > fdmax)
                                                        fdmax = f->fd[FFILE_IN];