diff options
| -rw-r--r-- | go.mod | 3 | ||||
| -rw-r--r-- | mc/mc.go | 60 | ||||
| -rw-r--r-- | networkQuality.go | 88 |
3 files changed, 151 insertions, 0 deletions
@@ -0,0 +1,3 @@ +module github.com/hawkinsw/goresponsiveness + +go 1.16 diff --git a/mc/mc.go b/mc/mc.go new file mode 100644 index 0000000..4d405de --- /dev/null +++ b/mc/mc.go @@ -0,0 +1,60 @@ +package mc + +import ( + "context" + "fmt" + "io" + "io/ioutil" + "net/http" +) + +type MeasurableConnection interface { + Start(context.Context) bool + Stop() bool + Downloaded() uint64 +} + +type LoadBearingConnection struct { + Path string + ctx context.Context + cancel context.CancelFunc + downloaded uint64 + client *http.Client +} + +func (lbc *LoadBearingConnection) Downloaded() uint64 { + return lbc.downloaded +} + +func (lbc *LoadBearingConnection) Start(ctx context.Context) bool { + fmt.Printf("Starting a LBC ...") + lbc.ctx, lbc.cancel = context.WithCancel(ctx) + lbc.downloaded = 0 + lbc.client = &http.Client{} + get, err := lbc.client.Get(lbc.Path) + + if err != nil { + return false + } + go doDownload(get, &lbc.downloaded, lbc.ctx) + return true +} + +func (lbc *LoadBearingConnection) Stop() bool { + lbc.cancel() + return true +} + +func doDownload(get *http.Response, count *uint64, ctx context.Context) { + for ctx.Err() == nil { + n, err := io.CopyN(ioutil.Discard, get.Body, 1024*1024) + if err != nil { + fmt.Printf("Done reading!\n") + break + } + fmt.Printf("Read some bytes: %d\n", n) + *count += uint64(n) + } + fmt.Printf("Cancelling my download.\n") + get.Body.Close() +} diff --git a/networkQuality.go b/networkQuality.go new file mode 100644 index 0000000..df58bbf --- /dev/null +++ b/networkQuality.go @@ -0,0 +1,88 @@ +package main + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "github.com/hawkinsw/goresponsiveness/mc" + _ "io" + "io/ioutil" + _ "log" + "net/http" + "time" +) + +type ConfigUrls struct { + SmallUrl string `json:"small_https_download_url"` + LargeUrl string `json:"large_https_download_url"` + UploadUrl string `json:"https_upload_url"` +} + +type Config struct { + Version int + Urls ConfigUrls `json:"urls"` +} + +func (c *Config) String() string { + return fmt.Sprintf("Version: %d\nSmall URL: %s\nLarge URL: %s\nUpload URL: %s", c.Version, c.Urls.SmallUrl, c.Urls.LargeUrl, c.Urls.UploadUrl) +} + +var ( + // Variables to hold CLI arguments. + configHost = flag.String("config", "networkquality.example.com", "name/IP of responsiveness configuration server.") + configPort = flag.Int("port", 4043, "port number on which to access responsiveness configuration server.") + debug = flag.Bool("debug", false, "Enable debugging.") +) + +func main() { + flag.Parse() + + configHostPort := fmt.Sprintf("%s:%d", *configHost, *configPort) + configUrl := fmt.Sprintf("https://%s/config", configHostPort) + + configClient := &http.Client{} + resp, err := configClient.Get(configUrl) + if err != nil { + fmt.Printf("Error connecting to %s: %v\n", configHostPort, err) + return + } + + jsonConfig, err := ioutil.ReadAll(resp.Body) + if err != nil { + fmt.Printf("Error reading content downloaded from %s: %v\n", configUrl, err) + return + } + + var config Config + err = json.Unmarshal(jsonConfig, &config) + if err != nil { + fmt.Printf("Error parsing configuration returned from %s: %v\n", configUrl, err) + return + } + + if *debug { + fmt.Printf("Configuration: %s\n", &config) + } + + time.Sleep(4 * time.Second) + + mcs := make([]*mc.LoadBearingConnection, 4) + for i := range mcs { + mcs[i] = &mc.LoadBearingConnection{Path: config.Urls.LargeUrl} + mcCtx := context.Background() + if !mcs[i].Start(mcCtx) { + fmt.Printf("Error starting %dth MC!\n", i) + return + } + } + + time.Sleep(4 * time.Second) + + for i := range mcs { + mcs[i].Stop() + fmt.Printf("mc[%d] read: %d\n", i, mcs[i].Downloaded()) + } + + time.Sleep(4 * time.Second) +} |
