summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod3
-rw-r--r--mc/mc.go60
-rw-r--r--networkQuality.go88
3 files changed, 151 insertions, 0 deletions
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..ee5ae7e
--- /dev/null
+++ b/go.mod
@@ -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)
+}