From: djm Date: Fri, 24 Jan 2003 00:36:58 +0000 (+0000) Subject: - markus@cvs.openbsd.org 2003/01/23 14:01:53 X-Git-Tag: V_3_6_P1~62 X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/commitdiff_plain/6ea3c52ab532aa360b7257e5fc286b98d7ed0646 - markus@cvs.openbsd.org 2003/01/23 14:01:53 [scp.c] bandwidth limitation patch (scp -l) from niels@; ok todd@, deraadt@ --- diff --git a/ChangeLog b/ChangeLog index 43c50412..56197a2d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,9 @@ ssh-add -c, prompt user for confirmation (using ssh-askpass) when private agent key is used; with djm@; test by dugsong@, djm@; ok deraadt@ + - markus@cvs.openbsd.org 2003/01/23 14:01:53 + [scp.c] + bandwidth limitation patch (scp -l) from niels@; ok todd@, deraadt@ 20030123 - (djm) OpenBSD CVS Sync diff --git a/scp.c b/scp.c index 616dd378..ae0a1ead 100644 --- a/scp.c +++ b/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" @@ -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(); @@ -647,6 +661,60 @@ rsource(name, statp) (void) response(); } +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; @@ -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); }