add files
This commit is contained in:
BIN
p2p/50.bin
Normal file
BIN
p2p/50.bin
Normal file
Binary file not shown.
13
p2p/README
Normal file
13
p2p/README
Normal file
@@ -0,0 +1,13 @@
|
||||
P2P module
|
||||
===========
|
||||
(Techniques to get over NAT)
|
||||
- UPNP implementation
|
||||
- DMZ to be used if UPNP does not work
|
||||
- Port forwarding for future release
|
||||
|
||||
(Discovery of Nodes)
|
||||
- Connect to reliable connection (that has some knowledge)
|
||||
- Check if the connection is still open (If not instruct the server to remove from table)
|
||||
- According speed tests
|
||||
- Send list of servers connection open
|
||||
- default 100 MB (to store tables of ip records)
|
||||
10
p2p/ip_table.json
Normal file
10
p2p/ip_table.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ip_address": [
|
||||
{
|
||||
"ipv4": "localhost",
|
||||
"latency": 14981051,
|
||||
"download": 8142.122540206258,
|
||||
"upload": 3578.766512629995
|
||||
}
|
||||
]
|
||||
}
|
||||
91
p2p/iptable.go
Normal file
91
p2p/iptable.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Get IP table Data
|
||||
|
||||
type IpAddresses struct {
|
||||
IpAddress []IpAddress `json:"ip_address"`
|
||||
}
|
||||
|
||||
type IpAddress struct {
|
||||
Ipv4 string `json:"ipv4"`
|
||||
Latency time.Duration `json:"latency"`
|
||||
Download float64 `json:"download"`
|
||||
Upload float64 `json:"upload"`
|
||||
}
|
||||
|
||||
// Read data from Ip tables from json file
|
||||
func ReadIpTable()(*IpAddresses ,error){
|
||||
// Get Path from config
|
||||
config, err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
|
||||
jsonFile, err := os.Open(config.SpeedTestFile)
|
||||
// if we os.Open returns an error then handle it
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
|
||||
|
||||
// defer the closing of our jsonFile so that we can parse it later on
|
||||
defer jsonFile.Close()
|
||||
|
||||
// read our opened xmlFile as a byte array.
|
||||
byteValue, _ := ioutil.ReadAll(jsonFile)
|
||||
|
||||
// we initialize our Users array
|
||||
var ipAddresses IpAddresses
|
||||
|
||||
// we unmarshal our byteArray which contains our
|
||||
// jsonFile's content into 'users' which we defined above
|
||||
json.Unmarshal(byteValue, &ipAddresses)
|
||||
|
||||
return &ipAddresses, nil
|
||||
}
|
||||
|
||||
// Write to IP table json file
|
||||
func (i *IpAddresses) WriteIpTable() error {
|
||||
file, err := json.MarshalIndent(i, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get Path from config
|
||||
config, err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(config.SpeedTestFile, file, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Print Ip table data for Cli
|
||||
func PrintIpTable() error {
|
||||
table, err := ReadIpTable()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < len(table.IpAddress); i++ {
|
||||
fmt.Printf("----------------------\nIP Address: %s\nLatency: %s\nDownload: %f\nUplaod: %f\n-----------" +
|
||||
"-----------\n",table.IpAddress[i].Ipv4,
|
||||
table.IpAddress[i].Latency,table.IpAddress[i].Download,table.IpAddress[i].Upload)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
22
p2p/iptable_test.go
Normal file
22
p2p/iptable_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReadIpTable(t *testing.T) {
|
||||
json, err := ReadIpTable()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = json.WriteIpTable()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = PrintIpTable()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
88
p2p/speedtest.go
Normal file
88
p2p/speedtest.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package p2p
|
||||
|
||||
// Runs a speed test and does updates IP tables accordingly
|
||||
func (ip *IpAddresses)SpeedTest() error{
|
||||
|
||||
for i, _ := range ip.IpAddress {
|
||||
// Ping Test
|
||||
err := ip.IpAddress[i].PingTest()
|
||||
if err != nil {
|
||||
// Remove IP address of element not pingable
|
||||
ip.IpAddress = append(ip.IpAddress[:i], ip.IpAddress[i+1:]...)
|
||||
// Proceed to next element in the array
|
||||
continue
|
||||
}
|
||||
|
||||
//Upload Speed Test
|
||||
err = ip.IpAddress[i].UploadSpeed()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ip.IpAddress[i].DownloadSpeed()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err := ip.WriteIpTable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Called when ip tables from client/server is also passed on
|
||||
func (ip *IpAddresses)SpeedTestUpdatedIPTable() error{
|
||||
targets, err := ReadIpTable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// To ensure struct has no duplicates IP addresses
|
||||
DoNotRead := targets
|
||||
|
||||
// Appends all IP addresses
|
||||
for i, _ := range targets.IpAddress {
|
||||
|
||||
Exists := false
|
||||
for k := range DoNotRead.IpAddress {
|
||||
if DoNotRead.IpAddress[k].Ipv4 == targets.IpAddress[i].Ipv4 {
|
||||
Exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If the struct exists then continues
|
||||
if Exists {
|
||||
continue
|
||||
}
|
||||
|
||||
ip.IpAddress = append(ip.IpAddress, targets.IpAddress[i])
|
||||
}
|
||||
|
||||
err = ip.SpeedTest()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Runs speed test in iptables locally only
|
||||
func LocalSpeedTestIpTable() error {
|
||||
targets, err := ReadIpTable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = targets.SpeedTest()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
21
p2p/speedtest/speedtest.go
Normal file
21
p2p/speedtest/speedtest.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/showwin/speedtest-go/speedtest"
|
||||
)
|
||||
|
||||
func main() {
|
||||
user, _ := speedtest.FetchUserInfo()
|
||||
|
||||
serverList, _ := speedtest.FetchServerList(user)
|
||||
targets, _ := serverList.FindServer([]int{})
|
||||
|
||||
for _, s := range targets {
|
||||
s.PingTest()
|
||||
s.DownloadTest(false)
|
||||
s.UploadTest(false)
|
||||
|
||||
fmt.Printf("Latency: %s, Download: %f, Upload: %f\n", s.Latency, s.DLSpeed, s.ULSpeed)
|
||||
}
|
||||
}
|
||||
16
p2p/speedtest_test.go
Normal file
16
p2p/speedtest_test.go
Normal file
@@ -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 := LocalSpeedTestIpTable()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
//HumaidTest("http://localhost:8088/50")
|
||||
//HumaidTest("http://ipv4.download.thinkbroadband.com/50MB.zip")
|
||||
}
|
||||
172
p2p/testingMetrics.go
Normal file
172
p2p/testingMetrics.go
Normal file
@@ -0,0 +1,172 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"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 + ":8088/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
|
||||
}
|
||||
|
||||
func (s *IpAddress)UploadSpeed() error {
|
||||
start := time.Now()
|
||||
|
||||
// Get upload file path from config file
|
||||
// Get Path from config
|
||||
config, err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b, w := createMultipartFormData("file",config.SpeedTestFile)
|
||||
|
||||
req, err := http.NewRequest("GET", "http://" + s.Ipv4 + ":8088/upload", &b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Don't forget to set the content type, this will contain the boundary.
|
||||
req.Header.Set("Content-Type", w.FormDataContentType())
|
||||
defer req.Body.Close()
|
||||
ioutil.ReadAll(req.Body)
|
||||
t := time.Since(start)
|
||||
//fmt.Println(s.Seconds())
|
||||
// size * time (seconds)
|
||||
s.Upload = (50/t.Seconds())*8
|
||||
return nil
|
||||
}
|
||||
|
||||
//Upload helper function for uploading
|
||||
//(https://stackoverflow.com/questions/20205796/post-data-using-the-content-type-multipart-form-data
|
||||
func createMultipartFormData(fieldName, fileName string) (bytes.Buffer, *multipart.Writer) {
|
||||
var b bytes.Buffer
|
||||
var err error
|
||||
w := multipart.NewWriter(&b)
|
||||
var fw io.Writer
|
||||
file := mustOpen(fileName)
|
||||
if fw, err = w.CreateFormFile(fieldName, file.Name()); err != nil {
|
||||
log.Fatalf("Error creating writer: %v", err)
|
||||
}
|
||||
if _, err = io.Copy(fw, file); err != nil {
|
||||
log.Fatalf("Error with io.Copy: %v", err)
|
||||
//t.Errorf("Error with io.Copy: %v", err)
|
||||
}
|
||||
w.Close()
|
||||
return b, w
|
||||
}
|
||||
|
||||
func mustOpen(f string) *os.File {
|
||||
r, err := os.Open(f)
|
||||
if err != nil {
|
||||
log.Fatalf("Error with mustOpen: %v",err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
76
p2p/upnp.go
Normal file
76
p2p/upnp.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package p2p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitlab.com/NebulousLabs/go-upnp"
|
||||
)
|
||||
|
||||
// Port forwarding to the router
|
||||
func ForwardPort(port int) error{
|
||||
// connect to router
|
||||
d, err := upnp.Discover()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// discover external IP
|
||||
ip, err := d.ExternalIP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Your external IP is:", ip)
|
||||
|
||||
// forward a port
|
||||
err = d.Forward(50498, "upnp test")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// record router's location
|
||||
loc := d.Location()
|
||||
|
||||
// connect to router directly
|
||||
d, err = upnp.Load(loc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// unForwardPort from router
|
||||
func UnForwardPort(port int) error{
|
||||
// connect to router
|
||||
d, err := upnp.Discover()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
// discover external IP
|
||||
ip, err := d.ExternalIP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Your external IP is:", ip)
|
||||
|
||||
|
||||
// un-forward a port
|
||||
err = d.Clear(50498)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// record router's location
|
||||
loc := d.Location()
|
||||
|
||||
// connect to router directly
|
||||
d, err = upnp.Load(loc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
21
p2p/upnp_test.go
Normal file
21
p2p/upnp_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package p2p
|
||||
|
||||
import(
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAddRemoveUpnp(t *testing.T){
|
||||
|
||||
// forwarding port 23241 via upnp
|
||||
err := ForwardPort(23241)
|
||||
if err != nil {
|
||||
t.Errorf("Error returned: %q", err)
|
||||
}
|
||||
|
||||
// unforwarding port 23241 via upnp
|
||||
err = UnForwardPort(23241)
|
||||
if err != nil {
|
||||
t.Errorf("Error returned: %q", err)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user