diff options
author | Damien Miller <djm@mindrot.org> | 2003-01-24 11:36:58 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2003-01-24 11:36:58 +1100 |
commit | ff74d748e941fd9078aa8ac3fddecd249ab8ceb2 (patch) | |
tree | c3ff1f35ce90cc872b0b9a1f79394072b971375e /scp.c | |
parent | 6c71179f6839ab49e4e8a91209eef85dc190d5f1 (diff) | |
download | openssh-git-ff74d748e941fd9078aa8ac3fddecd249ab8ceb2.tar.gz |
- markus@cvs.openbsd.org 2003/01/23 14:01:53
[scp.c]
bandwidth limitation patch (scp -l) from niels@; ok todd@, deraadt@
Diffstat (limited to 'scp.c')
-rw-r--r-- | scp.c | 80 |
1 files changed, 76 insertions, 4 deletions
@@ -75,7 +75,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: scp.c,v 1.98 2003/01/10 10:29:35 djm Exp $"); +RCSID("$OpenBSD: scp.c,v 1.99 2003/01/23 14:01:53 markus Exp $"); #include "xmalloc.h" #include "atomicio.h" @@ -90,9 +90,14 @@ extern char *__progname; char *__progname; #endif +void bwlimit(int); + /* Struct for addargs */ arglist args; +/* Bandwidth limit */ +off_t limit = 0; + /* Name of current file being transferred. */ char *curfile; @@ -206,7 +211,8 @@ main(argc, argv) char *argv[]; { int ch, fflag, tflag, status; - char *targ; + double speed; + char *targ, *endp; extern char *optarg; extern int optind; @@ -219,7 +225,7 @@ main(argc, argv) addargs(&args, "-oClearAllForwardings yes"); fflag = tflag = 0; - while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1) + while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q46S:o:F:")) != -1) switch (ch) { /* User-visible flags. */ case '4': @@ -239,6 +245,12 @@ main(argc, argv) case 'B': addargs(&args, "-oBatchmode yes"); break; + case 'l': + speed = strtod(optarg, &endp); + if (speed <= 0 || *endp != '\0') + usage(); + limit = speed * 1024; + break; case 'p': pflag = 1; break; @@ -578,6 +590,8 @@ next: (void) close(fd); haderr = result >= 0 ? EIO : errno; statbytes += result; } + if (limit) + bwlimit(amt); } if (showprogress) stop_progress_meter(); @@ -648,6 +662,60 @@ rsource(name, statp) } void +bwlimit(int amount) +{ + static struct timeval bwstart, bwend; + static int lamt, thresh = 16384; + u_int64_t wait; + struct timespec ts, rm; + + if (!timerisset(&bwstart)) { + gettimeofday(&bwstart, NULL); + return; + } + + lamt += amount; + if (lamt < thresh) + return; + + gettimeofday(&bwend, NULL); + timersub(&bwend, &bwstart, &bwend); + if (!timerisset(&bwend)) + return; + + lamt *= 8; + wait = (double)1000000L * lamt / limit; + + bwstart.tv_sec = wait / 1000000L; + bwstart.tv_usec = wait % 1000000L; + + if (timercmp(&bwstart, &bwend, >)) { + timersub(&bwstart, &bwend, &bwend); + + /* Adjust the wait time */ + if (bwend.tv_sec) { + thresh /= 2; + if (thresh < 2048) + thresh = 2048; + } else if (bwend.tv_usec < 100) { + thresh *= 2; + if (thresh > 32768) + thresh = 32768; + } + + TIMEVAL_TO_TIMESPEC(&bwend, &ts); + while (nanosleep(&ts, &rm) == -1) { + if (errno != EINTR) + break; + ts = rm; + } + } + + lamt = 0; + gettimeofday(&bwstart, NULL); +} + +void sink(argc, argv) int argc; char *argv[]; @@ -844,6 +912,10 @@ bad: run_err("%s: %s", np, strerror(errno)); cp += j; statbytes += j; } while (amt > 0); + + if (limit) + bwlimit(4096); + if (count == bp->cnt) { /* Keep reading so we stay sync'd up. */ if (wrerr == NO) { @@ -954,7 +1026,7 @@ usage(void) { (void) fprintf(stderr, "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n" - " [-c cipher] [-i identity] [-o option]\n" + " [-c cipher] [-i identity] [-l limit] [-o option]\n" " [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); exit(1); } |