summaryrefslogtreecommitdiffhomepage
path: root/util/progresstracking/progresstracking.go
diff options
context:
space:
mode:
authorPercy Wegmann <percy@tailscale.com>2024-03-19 21:54:37 -0500
committerPercy Wegmann <ox.to.a.cart@gmail.com>2024-03-27 08:53:52 -0500
commitbed818a9785fb6f7fa71004f41219ccd2371f9ae (patch)
tree6b914b5abcfec50bcab4ad3ff4405b3a69bb83e1 /util/progresstracking/progresstracking.go
parent0d8cd1645ac128bbdd979fb2cfb1db0b8a184955 (diff)
downloadtailscale-bed818a9785fb6f7fa71004f41219ccd2371f9ae.tar.xz
tailscale-bed818a9785fb6f7fa71004f41219ccd2371f9ae.zip
ipn/localapi: add support for multipart POST to file-put
This allows sending multiple files via Taildrop in one request. Progress is tracked via ipn.Notify. Updates tailscale/corp#18202 Signed-off-by: Percy Wegmann <percy@tailscale.com>
Diffstat (limited to 'util/progresstracking/progresstracking.go')
-rw-r--r--util/progresstracking/progresstracking.go39
1 files changed, 39 insertions, 0 deletions
diff --git a/util/progresstracking/progresstracking.go b/util/progresstracking/progresstracking.go
new file mode 100644
index 000000000..a9411fb46
--- /dev/null
+++ b/util/progresstracking/progresstracking.go
@@ -0,0 +1,39 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+// Package progresstracking provides wrappers around io.Reader and io.Writer
+// that track progress.
+package progresstracking
+
+import (
+ "io"
+ "time"
+)
+
+// NewReader wraps the given Reader with a progress tracking Reader that
+// reports progress at the following points:
+//
+// - First read
+// - Every read spaced at least interval since the prior read
+// - Last read
+func NewReader(r io.Reader, interval time.Duration, onProgress func(totalRead int, err error)) io.Reader {
+ return &reader{Reader: r, interval: interval, onProgress: onProgress}
+}
+
+type reader struct {
+ io.Reader
+ interval time.Duration
+ onProgress func(int, error)
+ lastTracked time.Time
+ totalRead int
+}
+
+func (r *reader) Read(p []byte) (int, error) {
+ n, err := r.Reader.Read(p)
+ r.totalRead += n
+ if time.Since(r.lastTracked) > r.interval || err != nil {
+ r.onProgress(r.totalRead, err)
+ r.lastTracked = time.Now()
+ }
+ return n, err
+}