diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2003-01-23 14:01:54 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2003-01-23 14:01:54 +0000 |
commit | 2ab6bdb048f4b5f51b8b2742c87f561d9f368c05 (patch) | |
tree | f18b9fc7cf658ef640857f0180c9d13ebd88ba1b /usr.bin/ssh | |
parent | dad96236271dcb55963b9fe8385f7812e71e67f7 (diff) |
bandwidth limitation patch (scp -l) from niels@; ok todd@, deraadt@
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r-- | usr.bin/ssh/scp.c | 80 |
1 files changed, 76 insertions, 4 deletions
diff --git a/usr.bin/ssh/scp.c b/usr.bin/ssh/scp.c index feb96521b2c..2f195ee33e5 100644 --- a/usr.bin/ssh/scp.c +++ b/usr.bin/ssh/scp.c @@ -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" @@ -86,9 +86,14 @@ RCSID("$OpenBSD: scp.c,v 1.98 2003/01/10 10:29:35 djm Exp $"); int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); +void bwlimit(int); + /* Struct for addargs */ arglist args; +/* Bandwidth limit */ +off_t limit = 0; + /* Name of current file being transferred. */ char *curfile; @@ -202,7 +207,8 @@ main(argc, argv) char *argv[]; { int ch, fflag, tflag, status; - char *targ; + double speed; + char *targ, *endp; extern char *optarg; extern int optind; @@ -213,7 +219,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': @@ -233,6 +239,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; @@ -562,6 +574,8 @@ next: (void) close(fd); haderr = result >= 0 ? EIO : errno; statbytes += result; } + if (limit) + bwlimit(amt); } if (showprogress) stop_progress_meter(); @@ -632,6 +646,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[]; @@ -828,6 +896,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) { @@ -930,7 +1002,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); } |