diff options
Diffstat (limited to 'lbc/lbc.go')
| -rw-r--r-- | lbc/lbc.go | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/lbc/lbc.go b/lbc/lbc.go new file mode 100644 index 0000000..82fe550 --- /dev/null +++ b/lbc/lbc.go @@ -0,0 +1,125 @@ +package lbc + +import ( + "context" + "fmt" + "io" + "io/ioutil" + "net/http" +) + +var chunkSize int = 5000 + +type LoadBearingConnection interface { + Start(context.Context, bool) bool + Transferred() uint64 + Client() *http.Client +} + +type LoadBearingConnectionDownload struct { + Path string + downloaded uint64 + client *http.Client +} + +func (lbd *LoadBearingConnectionDownload) Transferred() uint64 { + return lbd.downloaded +} + +func (lbd *LoadBearingConnectionDownload) Client() *http.Client { + return lbd.client +} + +func (lbd *LoadBearingConnectionDownload) Start(ctx context.Context, debug bool) bool { + lbd.downloaded = 0 + lbd.client = &http.Client{} + + // At some point this might be useful: It is a snippet of code that will enable + // logging of per-session TLS key material in order to make debugging easier in + // Wireshark. + /* + lbd.client = &http.Client{ + Transport: &http2.Transport{ + TLSClientConfig: &tls.Config{ + KeyLogWriter: w, + + Rand: utilities.RandZeroSource{}, // for reproducible output; don't do this. + InsecureSkipVerify: true, // test server certificate is not trusted. + }, + }, + } + */ + + if debug { + fmt.Printf("Started a load bearing download.\n") + } + go doDownload(ctx, lbd.client, lbd.Path, &lbd.downloaded, debug) + return true +} + +func doDownload(ctx context.Context, client *http.Client, path string, count *uint64, debug bool) { + get, err := client.Get(path) + if err != nil { + return + } + for ctx.Err() == nil { + n, err := io.CopyN(ioutil.Discard, get.Body, int64(chunkSize)) + if err != nil { + break + } + *count += uint64(n) + } + get.Body.Close() + if debug { + fmt.Printf("Ending a load-bearing download.\n") + } +} + +type LoadBearingConnectionUpload struct { + Path string + uploaded uint64 + client *http.Client +} + +func (lbu *LoadBearingConnectionUpload) Transferred() uint64 { + return lbu.uploaded +} + +func (lbd *LoadBearingConnectionUpload) Client() *http.Client { + return lbd.client +} + +type syntheticCountingReader struct { + n *uint64 + ctx context.Context +} + +func (s *syntheticCountingReader) Read(p []byte) (n int, err error) { + if s.ctx.Err() != nil { + return 0, io.EOF + } + err = nil + n = len(p) + n = chunkSize + *s.n += uint64(n) + return +} + +func doUpload(ctx context.Context, client *http.Client, path string, count *uint64, debug bool) bool { + *count = 0 + s := &syntheticCountingReader{n: count, ctx: ctx} + resp, _ := client.Post(path, "application/octet-stream", s) + resp.Body.Close() + if debug { + fmt.Printf("Ending a load-bearing upload.\n") + } + return true +} + +func (lbu *LoadBearingConnectionUpload) Start(ctx context.Context, debug bool) bool { + lbu.uploaded = 0 + lbu.client = &http.Client{} + fmt.Printf("Started a load bearing upload.\n") + go doUpload(ctx, lbu.client, lbu.Path, &lbu.uploaded, debug) + return true +} |
