From 710fb3cb8bc32eb1250f333b8184ba044f627ad5 Mon Sep 17 00:00:00 2001 From: Will Hawkins Date: Sat, 19 Mar 2022 20:33:24 -0400 Subject: Rename: Change bearing to generating The newest version of the specification replaces the term bearing with the term generating. This patch brings the updated language to the code to make it easier to track the implementation's conformance to the spec. --- constants/constants.go | 4 +- lbc/lbc.go | 218 ------------------------------------------------- lgc/lgc.go | 218 +++++++++++++++++++++++++++++++++++++++++++++++++ networkQuality.go | 92 ++++++++++----------- utilities/utilities.go | 2 +- 5 files changed, 267 insertions(+), 267 deletions(-) delete mode 100644 lbc/lbc.go create mode 100644 lgc/lgc.go diff --git a/constants/constants.go b/constants/constants.go index a94c777..1a060dd 100644 --- a/constants/constants.go +++ b/constants/constants.go @@ -4,14 +4,14 @@ import "time" var ( // The initial number of connections on a LBC. - StartingNumberOfLoadBearingConnections uint64 = 4 + StartingNumberOfLoadGeneratingConnections uint64 = 4 // The number of intervals for which to account in a moving-average // calculation. MovingAverageIntervalCount int = 4 // The number of intervals across which to consider a moving average stable. MovingAverageStabilitySpan int = 4 // The number of connections to add to a LBC when unsaturated. - AdditiveNumberOfLoadBearingConnections uint64 = 4 + AdditiveNumberOfLoadGeneratingConnections uint64 = 4 // The cutoff of the percent difference that defines instability. InstabilityDelta float64 = 5 diff --git a/lbc/lbc.go b/lbc/lbc.go deleted file mode 100644 index 50a4caa..0000000 --- a/lbc/lbc.go +++ /dev/null @@ -1,218 +0,0 @@ -/* - * This file is part of Go Responsiveness. - * - * Go Responsiveness is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software Foundation, - * either version 3 of the License, or (at your option) any later version. - * Go Responsiveness is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with Foobar. If not, see . - */ - -package lbc - -import ( - "context" - "crypto/tls" - "fmt" - "io" - "io/ioutil" - "net/http" - "sync/atomic" - - "github.com/network-quality/goresponsiveness/utilities" - "golang.org/x/net/http2" -) - -var chunkSize int = 5000 - -type LoadBearingConnection interface { - Start(context.Context, bool) bool - Transferred() uint64 - Client() *http.Client - IsValid() bool -} - -type LoadBearingConnectionDownload struct { - Path string - downloaded uint64 - client *http.Client - debug bool - valid bool - KeyLogger io.Writer -} - -func (lbd *LoadBearingConnectionDownload) Transferred() uint64 { - transferred := atomic.LoadUint64(&lbd.downloaded) - if lbd.debug { - fmt.Printf("download: Transferred: %v\n", transferred) - } - return transferred -} - -func (lbd *LoadBearingConnectionDownload) Client() *http.Client { - return lbd.client -} - -type countingReader struct { - n *uint64 - ctx context.Context - readable io.Reader -} - -func (cr *countingReader) Read(p []byte) (n int, err error) { - if cr.ctx.Err() != nil { - return 0, io.EOF - } - n, err = cr.readable.Read(p) - atomic.AddUint64(cr.n, uint64(n)) - return -} - -func (lbd *LoadBearingConnectionDownload) Start( - ctx context.Context, - debug bool, -) bool { - lbd.downloaded = 0 - transport := http2.Transport{} - - if !utilities.IsInterfaceNil(lbd.KeyLogger) { - if debug { - fmt.Printf( - "Using an SSL Key Logger for this load-bearing download.\n", - ) - } - - // The presence of a custom TLSClientConfig in a *generic* `transport` - // means that go will default to HTTP/1.1 and cowardly avoid HTTP/2: - // https://github.com/golang/go/blob/7ca6902c171b336d98adbb103d701a013229c806/src/net/http/transport.go#L278 - // Also, it would appear that the API's choice of HTTP vs HTTP2 can - // depend on whether the url contains - // https:// or http://: - // https://github.com/golang/go/blob/7ca6902c171b336d98adbb103d701a013229c806/src/net/http/transport.go#L74 - transport.TLSClientConfig = &tls.Config{ - KeyLogWriter: lbd.KeyLogger, - InsecureSkipVerify: true, - } - } - - lbd.client = &http.Client{Transport: &transport} - lbd.debug = debug - lbd.valid = true - - if debug { - fmt.Printf("Started a load-bearing download.\n") - } - go lbd.doDownload(ctx) - return true -} -func (lbd *LoadBearingConnectionDownload) IsValid() bool { - return lbd.valid -} - -func (lbd *LoadBearingConnectionDownload) doDownload(ctx context.Context) { - get, err := lbd.client.Get(lbd.Path) - if err != nil { - lbd.valid = false - return - } - cr := &countingReader{n: &lbd.downloaded, ctx: ctx, readable: get.Body} - _, _ = io.Copy(ioutil.Discard, cr) - get.Body.Close() - if lbd.debug { - fmt.Printf("Ending a load-bearing download.\n") - } -} - -type LoadBearingConnectionUpload struct { - Path string - uploaded uint64 - client *http.Client - debug bool - valid bool - KeyLogger io.Writer -} - -func (lbu *LoadBearingConnectionUpload) Transferred() uint64 { - transferred := atomic.LoadUint64(&lbu.uploaded) - if lbu.debug { - fmt.Printf("upload: Transferred: %v\n", transferred) - } - return transferred -} - -func (lbu *LoadBearingConnectionUpload) Client() *http.Client { - return lbu.client -} - -func (lbu *LoadBearingConnectionUpload) IsValid() bool { - return lbu.valid -} - -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) - - atomic.AddUint64(s.n, uint64(n)) - return -} - -func (lbu *LoadBearingConnectionUpload) doUpload(ctx context.Context) bool { - lbu.uploaded = 0 - s := &syntheticCountingReader{n: &lbu.uploaded, ctx: ctx} - var resp *http.Response = nil - var err error - - if resp, err = lbu.client.Post(lbu.Path, "application/octet-stream", s); err != nil { - lbu.valid = false - } - resp.Body.Close() - if lbu.debug { - fmt.Printf("Ending a load-bearing upload.\n") - } - return true -} - -func (lbu *LoadBearingConnectionUpload) Start( - ctx context.Context, - debug bool, -) bool { - lbu.uploaded = 0 - - // See above for the rationale of doing http2.Transport{} here - // to ensure that we are using h2. - transport := http2.Transport{} - - if !utilities.IsInterfaceNil(lbu.KeyLogger) { - if debug { - fmt.Printf( - "Using an SSL Key Logger for this load-bearing upload.\n", - ) - } - transport.TLSClientConfig = &tls.Config{ - KeyLogWriter: lbu.KeyLogger, - InsecureSkipVerify: true, - } - } - - lbu.client = &http.Client{Transport: &transport} - lbu.debug = debug - lbu.valid = true - - if debug { - fmt.Printf("Started a load-bearing upload.\n") - } - go lbu.doUpload(ctx) - return true -} diff --git a/lgc/lgc.go b/lgc/lgc.go new file mode 100644 index 0000000..dd454c1 --- /dev/null +++ b/lgc/lgc.go @@ -0,0 +1,218 @@ +/* + * This file is part of Go Responsiveness. + * + * Go Responsiveness is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * Go Responsiveness is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with Foobar. If not, see . + */ + +package lgc + +import ( + "context" + "crypto/tls" + "fmt" + "io" + "io/ioutil" + "net/http" + "sync/atomic" + + "github.com/network-quality/goresponsiveness/utilities" + "golang.org/x/net/http2" +) + +var chunkSize int = 5000 + +type LoadGeneratingConnection interface { + Start(context.Context, bool) bool + Transferred() uint64 + Client() *http.Client + IsValid() bool +} + +type LoadGeneratingConnectionDownload struct { + Path string + downloaded uint64 + client *http.Client + debug bool + valid bool + KeyLogger io.Writer +} + +func (lbd *LoadGeneratingConnectionDownload) Transferred() uint64 { + transferred := atomic.LoadUint64(&lbd.downloaded) + if lbd.debug { + fmt.Printf("download: Transferred: %v\n", transferred) + } + return transferred +} + +func (lbd *LoadGeneratingConnectionDownload) Client() *http.Client { + return lbd.client +} + +type countingReader struct { + n *uint64 + ctx context.Context + readable io.Reader +} + +func (cr *countingReader) Read(p []byte) (n int, err error) { + if cr.ctx.Err() != nil { + return 0, io.EOF + } + n, err = cr.readable.Read(p) + atomic.AddUint64(cr.n, uint64(n)) + return +} + +func (lbd *LoadGeneratingConnectionDownload) Start( + ctx context.Context, + debug bool, +) bool { + lbd.downloaded = 0 + transport := http2.Transport{} + + if !utilities.IsInterfaceNil(lbd.KeyLogger) { + if debug { + fmt.Printf( + "Using an SSL Key Logger for this load-generating download.\n", + ) + } + + // The presence of a custom TLSClientConfig in a *generic* `transport` + // means that go will default to HTTP/1.1 and cowardly avoid HTTP/2: + // https://github.com/golang/go/blob/7ca6902c171b336d98adbb103d701a013229c806/src/net/http/transport.go#L278 + // Also, it would appear that the API's choice of HTTP vs HTTP2 can + // depend on whether the url contains + // https:// or http://: + // https://github.com/golang/go/blob/7ca6902c171b336d98adbb103d701a013229c806/src/net/http/transport.go#L74 + transport.TLSClientConfig = &tls.Config{ + KeyLogWriter: lbd.KeyLogger, + InsecureSkipVerify: true, + } + } + + lbd.client = &http.Client{Transport: &transport} + lbd.debug = debug + lbd.valid = true + + if debug { + fmt.Printf("Started a load-generating download.\n") + } + go lbd.doDownload(ctx) + return true +} +func (lbd *LoadGeneratingConnectionDownload) IsValid() bool { + return lbd.valid +} + +func (lbd *LoadGeneratingConnectionDownload) doDownload(ctx context.Context) { + get, err := lbd.client.Get(lbd.Path) + if err != nil { + lbd.valid = false + return + } + cr := &countingReader{n: &lbd.downloaded, ctx: ctx, readable: get.Body} + _, _ = io.Copy(ioutil.Discard, cr) + get.Body.Close() + if lbd.debug { + fmt.Printf("Ending a load-generating download.\n") + } +} + +type LoadGeneratingConnectionUpload struct { + Path string + uploaded uint64 + client *http.Client + debug bool + valid bool + KeyLogger io.Writer +} + +func (lbu *LoadGeneratingConnectionUpload) Transferred() uint64 { + transferred := atomic.LoadUint64(&lbu.uploaded) + if lbu.debug { + fmt.Printf("upload: Transferred: %v\n", transferred) + } + return transferred +} + +func (lbu *LoadGeneratingConnectionUpload) Client() *http.Client { + return lbu.client +} + +func (lbu *LoadGeneratingConnectionUpload) IsValid() bool { + return lbu.valid +} + +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) + + atomic.AddUint64(s.n, uint64(n)) + return +} + +func (lbu *LoadGeneratingConnectionUpload) doUpload(ctx context.Context) bool { + lbu.uploaded = 0 + s := &syntheticCountingReader{n: &lbu.uploaded, ctx: ctx} + var resp *http.Response = nil + var err error + + if resp, err = lbu.client.Post(lbu.Path, "application/octet-stream", s); err != nil { + lbu.valid = false + } + resp.Body.Close() + if lbu.debug { + fmt.Printf("Ending a load-generating upload.\n") + } + return true +} + +func (lbu *LoadGeneratingConnectionUpload) Start( + ctx context.Context, + debug bool, +) bool { + lbu.uploaded = 0 + + // See above for the rationale of doing http2.Transport{} here + // to ensure that we are using h2. + transport := http2.Transport{} + + if !utilities.IsInterfaceNil(lbu.KeyLogger) { + if debug { + fmt.Printf( + "Using an SSL Key Logger for this load-generating upload.\n", + ) + } + transport.TLSClientConfig = &tls.Config{ + KeyLogWriter: lbu.KeyLogger, + InsecureSkipVerify: true, + } + } + + lbu.client = &http.Client{Transport: &transport} + lbu.debug = debug + lbu.valid = true + + if debug { + fmt.Printf("Started a load-generating upload.\n") + } + go lbu.doUpload(ctx) + return true +} diff --git a/networkQuality.go b/networkQuality.go index 41caa4c..135a10f 100644 --- a/networkQuality.go +++ b/networkQuality.go @@ -33,7 +33,7 @@ import ( "github.com/network-quality/goresponsiveness/ccw" "github.com/network-quality/goresponsiveness/constants" - "github.com/network-quality/goresponsiveness/lbc" + "github.com/network-quality/goresponsiveness/lgc" "github.com/network-quality/goresponsiveness/ma" "github.com/network-quality/goresponsiveness/timeoutat" "github.com/network-quality/goresponsiveness/utilities" @@ -196,16 +196,16 @@ func (c *Config) IsValid() error { func addFlows( ctx context.Context, toAdd uint64, - lbcs *[]lbc.LoadBearingConnection, - lbcsPreviousTransferred *[]uint64, - lbcGenerator func() lbc.LoadBearingConnection, + lgcs *[]lgc.LoadGeneratingConnection, + lgcsPreviousTransferred *[]uint64, + lgcGenerator func() lgc.LoadGeneratingConnection, debug bool, ) { for i := uint64(0); i < toAdd; i++ { - *lbcs = append(*lbcs, lbcGenerator()) - *lbcsPreviousTransferred = append(*lbcsPreviousTransferred, 0) - if !(*lbcs)[len(*lbcs)-1].Start(ctx, debug) { - fmt.Printf("Error starting %dth LBC!\n", i) + *lgcs = append(*lgcs, lgcGenerator()) + *lgcsPreviousTransferred = append(*lgcsPreviousTransferred, 0) + if !(*lgcs)[len(*lgcs)-1].Start(ctx, debug) { + fmt.Printf("Error starting %dth lgc!\n", i) return } } @@ -213,7 +213,7 @@ func addFlows( type SaturationResult struct { RateBps float64 - Lbcs []lbc.LoadBearingConnection + lgcs []lgc.LoadGeneratingConnection } type Debugging struct { @@ -231,21 +231,21 @@ func (d *Debugging) String() string { func saturate( saturationCtx context.Context, operatingCtx context.Context, - lbcGenerator func() lbc.LoadBearingConnection, + lgcGenerator func() lgc.LoadGeneratingConnection, debug *Debugging, ) (saturated chan SaturationResult) { saturated = make(chan SaturationResult) go func() { - lbcs := make([]lbc.LoadBearingConnection, 0) - lbcsPreviousTransferred := make([]uint64, 0) + lgcs := make([]lgc.LoadGeneratingConnection, 0) + lgcsPreviousTransferred := make([]uint64, 0) addFlows( saturationCtx, - constants.StartingNumberOfLoadBearingConnections, - &lbcs, - &lbcsPreviousTransferred, - lbcGenerator, + constants.StartingNumberOfLoadGeneratingConnections, + &lgcs, + &lgcsPreviousTransferred, + lgcGenerator, debug != nil, ) @@ -293,11 +293,11 @@ func saturate( // bytes transferred within the last second. totalTransfer := uint64(0) allInvalid := true - for i := range lbcs { - if !lbcs[i].IsValid() { + for i := range lgcs { + if !lgcs[i].IsValid() { if debug != nil { fmt.Printf( - "%v: Load-bearing connection at index %d is invalid ... skipping.\n", + "%v: Load-generating connection at index %d is invalid ... skipping.\n", debug, i, ) @@ -305,18 +305,18 @@ func saturate( continue } allInvalid = false - previousTransferred := lbcsPreviousTransferred[i] - currentTransferred := lbcs[i].Transferred() + previousTransferred := lgcsPreviousTransferred[i] + currentTransferred := lgcs[i].Transferred() totalTransfer += (currentTransferred - previousTransferred) - lbcsPreviousTransferred[i] = currentTransferred + lgcsPreviousTransferred[i] = currentTransferred } - // For some reason, all the LBCs are invalid. This likely means that + // For some reason, all the lgcs are invalid. This likely means that // the network/server went away. if allInvalid { if debug != nil { fmt.Printf( - "%v: All LBCs were invalid. Assuming that network/server went away.\n", + "%v: All lgcs were invalid. Assuming that network/server went away.\n", debug, ) } @@ -380,10 +380,10 @@ func saturate( } addFlows( saturationCtx, - constants.AdditiveNumberOfLoadBearingConnections, - &lbcs, - &lbcsPreviousTransferred, - lbcGenerator, + constants.AdditiveNumberOfLoadGeneratingConnections, + &lgcs, + &lgcsPreviousTransferred, + lgcGenerator, debug != nil, ) previousFlowIncreaseIteration = currentIteration @@ -408,13 +408,13 @@ func saturate( if debug != nil { fmt.Printf("%v: New flows to add to try to increase our saturation!\n", debug) } - addFlows(saturationCtx, constants.AdditiveNumberOfLoadBearingConnections, &lbcs, &lbcsPreviousTransferred, lbcGenerator, debug != nil) + addFlows(saturationCtx, constants.AdditiveNumberOfLoadGeneratingConnections, &lgcs, &lgcsPreviousTransferred, lgcGenerator, debug != nil) previousFlowIncreaseIteration = currentIteration } } } - saturated <- SaturationResult{RateBps: movingAverage.CalculateAverage(), Lbcs: lbcs} + saturated <- SaturationResult{RateBps: movingAverage.CalculateAverage(), lgcs: lgcs} }() return } @@ -499,14 +499,14 @@ func main() { } } - generate_lbd := func() lbc.LoadBearingConnection { - return &lbc.LoadBearingConnectionDownload{ + generate_lbd := func() lgc.LoadGeneratingConnection { + return &lgc.LoadGeneratingConnectionDownload{ Path: config.Urls.LargeUrl, KeyLogger: sslKeyFileConcurrentWriter, } } - generate_lbu := func() lbc.LoadBearingConnection { - return &lbc.LoadBearingConnectionUpload{ + generate_lbu := func() lgc.LoadGeneratingConnection { + return &lgc.LoadGeneratingConnectionUpload{ Path: config.Urls.UploadUrl, KeyLogger: sslKeyFileConcurrentWriter, } @@ -552,7 +552,7 @@ func main() { "", ), utilities.ToMBps(downloadSaturation.RateBps), - len(downloadSaturation.Lbcs), + len(downloadSaturation.lgcs), ) } } @@ -568,7 +568,7 @@ func main() { "", ), utilities.ToMBps(uploadSaturation.RateBps), - len(uploadSaturation.Lbcs), + len(uploadSaturation.lgcs), ) } } @@ -629,20 +629,20 @@ func main() { rttTimeout := false for i := 0; i < constants.RPMProbeCount && !rttTimeout; i++ { - if len(downloadSaturation.Lbcs) == 0 { + if len(downloadSaturation.lgcs) == 0 { continue } - randomLbcsIndex := rand.New(rand.NewSource(int64(time.Now().Nanosecond()))). + randomlgcsIndex := rand.New(rand.NewSource(int64(time.Now().Nanosecond()))). Int() % len( - downloadSaturation.Lbcs, + downloadSaturation.lgcs, ) - if !downloadSaturation.Lbcs[randomLbcsIndex].IsValid() { + if !downloadSaturation.lgcs[randomlgcsIndex].IsValid() { if *debug { fmt.Printf( - "%v: The randomly selected download LBC (at index %d) was invalid. Skipping.\n", + "%v: The randomly selected download lgc (at index %d) was invalid. Skipping.\n", debug, - randomLbcsIndex, + randomlgcsIndex, ) } @@ -652,7 +652,7 @@ func main() { if time.Since(timeoutAbsoluteTime) > 0 { if *debug { fmt.Printf( - "Pathologically could not find valid LBCs to use for measurement.\n", + "Pathologically could not find valid lgcs to use for measurement.\n", ) } break @@ -674,7 +674,7 @@ func main() { { rttTimeout = true } - case sequentialRTTimes := <-utilities.CalculateSequentialRTTsTime(operatingCtx, downloadSaturation.Lbcs[randomLbcsIndex].Client(), &newClient, config.Urls.SmallUrl): + case sequentialRTTimes := <-utilities.CalculateSequentialRTTsTime(operatingCtx, downloadSaturation.lgcs[randomlgcsIndex].Client(), &newClient, config.Urls.SmallUrl): { if sequentialRTTimes.Err != nil { fmt.Printf( @@ -700,13 +700,13 @@ func main() { "Download: %7.3f Mbps (%7.3f MBps), using %d parallel connections.\n", utilities.ToMbps(downloadSaturation.RateBps), utilities.ToMBps(downloadSaturation.RateBps), - len(downloadSaturation.Lbcs), + len(downloadSaturation.lgcs), ) fmt.Printf( "Upload: %7.3f Mbps (%7.3f MBps), using %d parallel connections.\n", utilities.ToMbps(uploadSaturation.RateBps), utilities.ToMBps(uploadSaturation.RateBps), - len(uploadSaturation.Lbcs), + len(uploadSaturation.lgcs), ) if totalRTsCount != 0 { diff --git a/utilities/utilities.go b/utilities/utilities.go index 8b64da4..46d5766 100644 --- a/utilities/utilities.go +++ b/utilities/utilities.go @@ -79,7 +79,7 @@ func CalculateSequentialRTTsTime( roundTripCount := uint16(0) before := time.Now() /* - TODO: We are not going to measure round-trip times on the load-bearing connection + TODO: We are not going to measure round-trip times on the load-generating connection right now because we are dealing with a massive amount of buffer bloat on the Apple CDN. -- cgit v1.2.3