diff --git a/go.mod b/go.mod index 35667c3..f365680 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/go-ole/go-ole v1.2.5 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.5.4 // indirect + github.com/google/uuid v1.1.2 github.com/gorilla/mux v1.8.0 // indirect github.com/grandcat/zeroconf v1.0.0 github.com/kr/pretty v0.1.0 // indirect @@ -30,6 +31,7 @@ require ( gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3 golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect + golang.org/x/sync v0.0.0-20201207232520-09787c993a3a golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect google.golang.org/grpc v1.35.0 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect diff --git a/go.sum b/go.sum index 18e4956..35c8473 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= diff --git a/main b/main deleted file mode 100755 index eac34bb..0000000 Binary files a/main and /dev/null differ diff --git a/main.go b/main.go index 706208c..84109b2 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,10 @@ package main import ( + "github.com/urfave/cli/v2" "log" "os" - "github.com/urfave/cli/v2" + _ "git.sr.ht/~akilan1999/p2p-rendering-computation/p2p" //"fmt" "git.sr.ht/~akilan1999/p2p-rendering-computation/server" ) diff --git a/p2p/ip_table.json b/p2p/ip_table.json index c129c46..f2f0382 100644 --- a/p2p/ip_table.json +++ b/p2p/ip_table.json @@ -1,10 +1,7 @@ { "ip_address":[ { - "ipv4":"23.23.232.2", - "latency":3, - "download": 34, - "upload": 50 + "ipv4":"localhost" } ] } diff --git a/p2p/readiptable.go b/p2p/readiptable.go index cdad132..78ca0e4 100644 --- a/p2p/readiptable.go +++ b/p2p/readiptable.go @@ -4,6 +4,7 @@ import ( "encoding/json" "io/ioutil" "os" + "time" ) // Get IP table Data @@ -14,9 +15,9 @@ type IpAddresses struct { type IpAddress struct { Ipv4 string `json:"ipv4"` - Latency float32 `json:"latency"` - Download float32 `json:"download"` - Upload float32 `json:"upload"` + Latency time.Duration `json:"latency"` + Download float64 `json:"download"` + Upload float64 `json:"upload"` } func ReadIpTable()(*IpAddresses ,error){ diff --git a/p2p/speedtest.go b/p2p/speedtest.go new file mode 100644 index 0000000..cc839d9 --- /dev/null +++ b/p2p/speedtest.go @@ -0,0 +1,63 @@ +package p2p + +import ( + "fmt" + "time" +) + +type Server struct { + URL string `xml:"url,attr"` + Lat string `xml:"lat,attr"` + Lon string `xml:"lon,attr"` + Name string `xml:"name,attr"` + Country string `xml:"country,attr"` + Sponsor string `xml:"sponsor,attr"` + ID string `xml:"id,attr"` + URL2 string `xml:"url2,attr"` + Host string `xml:"host,attr"` + Distance float64 + Latency time.Duration + DLSpeed float64 + ULSpeed float64 +} + + +func SpeedTest() error{ + + targets, err := ReadIpTable() + + if err != nil { + return err + } + //serverList, _ := speedtest.FetchServerList(user) + //targets, _ := serverList.FindServer([]int{}) + + for _, s := range targets.IpAddress { + //fmt.Print(strings.Split(i., "/upload")[0] + "/latency.txt") + // Ping Test + err = s.PingTest() + if err != nil { + return err + } + + //Upload Speed Test + err = s.UploadTest(false) + if err != nil { + return err + } + + err = s.DownloadSpeed() + if err != nil { + return err + } + + //s.DownloadTest(false) + //s.UploadTest(false) + fmt.Println(s.Download) + //fmt.Printf("Latency: %s, Download: %f, Upload: %f\n", s.Latency, s.DLSpeed, s.ULSpeed) + } + + return nil +} + + diff --git a/p2p/speedtest/speedtest.go b/p2p/speedtest/speedtest.go index 8cd597a..9aaab28 100644 --- a/p2p/speedtest/speedtest.go +++ b/p2p/speedtest/speedtest.go @@ -3,69 +3,19 @@ package main import ( "fmt" "github.com/showwin/speedtest-go/speedtest" - "net/http" - "strings" - "time" ) -type Server struct { - URL string `xml:"url,attr"` - Lat string `xml:"lat,attr"` - Lon string `xml:"lon,attr"` - Name string `xml:"name,attr"` - Country string `xml:"country,attr"` - Sponsor string `xml:"sponsor,attr"` - ID string `xml:"id,attr"` - URL2 string `xml:"url2,attr"` - Host string `xml:"host,attr"` - Distance float64 - Latency time.Duration - DLSpeed float64 - ULSpeed float64 -} - - func main() { - SpeedTest() -} - -func SpeedTest() { user, _ := speedtest.FetchUserInfo() serverList, _ := speedtest.FetchServerList(user) targets, _ := serverList.FindServer([]int{}) for _, s := range targets { - fmt.Print(strings.Split(s.URL, "/upload")[0] + "/latency.txt") s.PingTest() s.DownloadTest(false) s.UploadTest(false) fmt.Printf("Latency: %s, Download: %f, Upload: %f\n", s.Latency, s.DLSpeed, s.ULSpeed) } -} - -// PingTest executes test to measure latency -// Function modified for custom URl -func (s *Server) PingTest() error { - pingURL := strings.Split(s.URL, "/upload")[0] + "/latency.txt" - fmt.Print(pingURL) - - l := time.Duration(100000000000) // 10sec - for i := 0; i < 3; i++ { - sTime := time.Now() - resp, err := http.Get(pingURL) - fTime := time.Now() - if err != nil { - return err - } - if fTime.Sub(sTime) < l { - l = fTime.Sub(sTime) - } - resp.Body.Close() - } - - s.Latency = time.Duration(int64(l.Nanoseconds() / 2)) - - return nil -} +} \ No newline at end of file diff --git a/p2p/speedtest_test.go b/p2p/speedtest_test.go new file mode 100644 index 0000000..cf98032 --- /dev/null +++ b/p2p/speedtest_test.go @@ -0,0 +1,16 @@ +package p2p + +import ( + "testing" +) + +// To run this test ip_table.json must be populated +func TestServer_SpeedTest(t *testing.T) { + err := SpeedTest() + if err != nil { + t.Fatal(err) + } + + //HumaidTest("http://localhost:8088/50") + //HumaidTest("http://ipv4.download.thinkbroadband.com/50MB.zip") +} \ No newline at end of file diff --git a/p2p/testingMetrics.go b/p2p/testingMetrics.go new file mode 100644 index 0000000..66ceaac --- /dev/null +++ b/p2p/testingMetrics.go @@ -0,0 +1,234 @@ +package p2p + +import ( + "golang.org/x/sync/errgroup" + "io/ioutil" + "net/http" + "net/url" + "strconv" + "strings" + "time" +) + +var dlSizes = [...]int{350, 500, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000} +var ulSizes = [...]int{100, 300, 500, 800, 1000, 1500, 2500, 3000, 3500, 4000} //kB +var client = http.Client{} + +// DownloadTest executes the test to measure download speed +func (s *IpAddress) DownloadTest(savingMode bool) error { + dlURL := "http://" + s.Ipv4 + ":8088/server_info" + eg := errgroup.Group{} + + // Warming up + sTime := time.Now() + for i := 0; i < 2; i++ { + eg.Go(func() error { + return dlWarmUp("http://" + s.Ipv4 + ":8088/server_info") + }) + } + if err := eg.Wait(); err != nil { + return err + } + fTime := time.Now() + // 1.125MB for each request (750 * 750 * 2) + wuSpeed := 1.125 * 8 * 2 / fTime.Sub(sTime.Add(s.Latency)).Seconds() + + // Decide workload by warm up speed + workload := 0 + weight := 0 + skip := false + if savingMode { + workload = 6 + weight = 3 + } else if 10.0 < wuSpeed { + workload = 16 + weight = 4 + } else if 4.0 < wuSpeed { + workload = 8 + weight = 4 + } else if 2.5 < wuSpeed { + workload = 4 + weight = 4 + } else { + skip = true + } + + // Main speedtest + dlSpeed := wuSpeed + if skip == false { + sTime = time.Now() + for i := 0; i < workload; i++ { + eg.Go(func() error { + return downloadRequest(dlURL, weight) + }) + } + if err := eg.Wait(); err != nil { + return err + } + fTime = time.Now() + + reqMB := dlSizes[weight] * dlSizes[weight] * 2 / 1000 / 1000 + dlSpeed = float64(reqMB) * 8 * float64(workload) / fTime.Sub(sTime).Seconds() + } + + s.Download = dlSpeed + return nil +} + +// Download Speed +func (s *IpAddress)DownloadSpeed() error { + start := time.Now() + resp, err := client.Get("http://" + s.Ipv4 + ":8080/50") + if err != nil { + return err + } + defer resp.Body.Close() + ioutil.ReadAll(resp.Body) + t := time.Since(start) + //fmt.Println(s.Seconds()) + // size * time (seconds) + s.Download = (50/t.Seconds())*8 + return nil +} + +// UploadTest executes the test to measure upload speed +func (s *IpAddress) UploadTest(savingMode bool) error { + // Warm up + sTime := time.Now() + eg := errgroup.Group{} + for i := 0; i < 2; i++ { + eg.Go(func() error { + return ulWarmUp("http://" + s.Ipv4 + ":8088/server_info") + }) + } + if err := eg.Wait(); err != nil { + return err + } + fTime := time.Since(sTime) + // 1.0 MB for each request + wuSpeed := 1.0 * 8 * 2 / (fTime.Seconds() + s.Latency.Seconds()) + + // Decide workload by warm up speed + workload := 0 + weight := 0 + skip := false + if savingMode { + workload = 1 + weight = 7 + } else if 10.0 < wuSpeed { + workload = 16 + weight = 9 + } else if 4.0 < wuSpeed { + workload = 8 + weight = 9 + } else if 2.5 < wuSpeed { + workload = 4 + weight = 5 + } else { + skip = true + } + + // Main speedtest + ulSpeed := wuSpeed + if skip == false { + sTime = time.Now() + for i := 0; i < workload; i++ { + eg.Go(func() error { + return uploadRequest("http://"+s.Ipv4+":8088/server_info") + }) + } + if err := eg.Wait(); err != nil { + return err + } + fTime := time.Since(sTime) + + reqMB := float64(ulSizes[weight]) / 1000 + ulSpeed = reqMB * 8 * float64(workload) / fTime.Seconds() + } + + s.Upload = ulSpeed + + return nil +} + +func dlWarmUp(dlURL string) error { + size := dlSizes[2] + xdlURL := dlURL + "/random" + strconv.Itoa(size) + "x" + strconv.Itoa(size) + ".jpg" + + resp, err := client.Get(xdlURL) + if err != nil { + return err + } + defer resp.Body.Close() + ioutil.ReadAll(resp.Body) + + return nil +} + +func ulWarmUp(ulURL string) error { + size := ulSizes[4] + v := url.Values{} + v.Add("content", strings.Repeat("0123456789", size*100-51)) + + resp, err := client.PostForm(ulURL, v) + if err != nil { + return err + } + defer resp.Body.Close() + ioutil.ReadAll(resp.Body) + + return nil +} + +func downloadRequest(dlURL string, w int) error { + size := dlSizes[w] + xdlURL := dlURL + "/random" + strconv.Itoa(size) + "x" + strconv.Itoa(size) + ".jpg" + + resp, err := client.Get(xdlURL) + if err != nil { + return err + } + defer resp.Body.Close() + ioutil.ReadAll(resp.Body) + + return nil +} + +func uploadRequest(ulURL string) error { + size := ulSizes[9] + v := url.Values{} + v.Add("content", strings.Repeat("0123456789", size*100-51)) + + resp, err := client.PostForm(ulURL, v) + if err != nil { + return err + } + defer resp.Body.Close() + ioutil.ReadAll(resp.Body) + + return nil +} + +// PingTest executes test to measure latency +func (s *IpAddress) PingTest() error { + //pingURL := strings.Split(s.URL, "/upload")[0] + "/latency.txt" + pingURL := "http://" + s.Ipv4 + ":8088/server_info" + l := time.Duration(100000000000) // 10sec + for i := 0; i < 3; i++ { + sTime := time.Now() + resp, err := http.Get(pingURL) + fTime := time.Now() + if err != nil { + return err + } + if fTime.Sub(sTime) < l { + l = fTime.Sub(sTime) + } + resp.Body.Close() + } + + s.Latency = time.Duration(int64(l.Nanoseconds() / 2)) + + return nil +} + diff --git a/server/50.bin b/server/50.bin new file mode 100644 index 0000000..151a7c2 Binary files /dev/null and b/server/50.bin differ diff --git a/server/server.go b/server/server.go index 3ee612b..149d2fc 100644 --- a/server/server.go +++ b/server/server.go @@ -16,6 +16,11 @@ func Server() { c.JSON(http.StatusOK, ServerInfo()) }) + // Speed test with 50 mbps + r.GET("/50", func(c *gin.Context){ + c.File("server/50.bin") + }) + // Route build to do a speed test r.GET("/upload", func(c *gin.Context) { file, _ := c.FormFile("file")