fixed pass through custom information

This commit is contained in:
2025-06-04 15:51:07 +01:00
parent 6a24da74ef
commit 3c3cfac5e2
5 changed files with 744 additions and 726 deletions

View File

@@ -31,9 +31,11 @@ P2PRC_instances() {
p2prc --as 0.0.0.0 -p "$NEW_PORT" p2prc --as 0.0.0.0 -p "$NEW_PORT"
# Replace the ServerPort in config # Replace the ServerPort in config
# test-$counter
sed -i.bak "s/\"ServerPort\": \"[0-9]*\"/\"ServerPort\": \"$NEW_PORT\"/" "./config.json" sed -i.bak "s/\"ServerPort\": \"[0-9]*\"/\"ServerPort\": \"$NEW_PORT\"/" "./config.json"
sed -i.bak "s/\"Test\": false/\"Test\": true/" "./config.json" sed -i.bak "s/\"Test\": false/\"Test\": true/" "./config.json"
sed -i.bak "s/\"BehindNAT\": true/\"BehindNAT\": false/" "./config.json" sed -i.bak "s/\"BehindNAT\": true/\"BehindNAT\": false/" "./config.json"
# sed -i.bak "s/\"MachineName\": "Akilans-MacBook-Pro.local-J2UbbkF"/\"MachineName\": \"test-$counter\"/" "./config.json"
cat config.json cat config.json
@@ -92,6 +94,15 @@ Update_All_IP_Tables() {
done done
} }
# Test function for the root to custom information
# through the network
Send_Information() {
ls
cd test-2/
p2prc --amd "test message"
cd ..
}
# ---------------- Work flow test --------------- # ---------------- Work flow test ---------------
@@ -104,6 +115,12 @@ P2PRC_instances 3
## Start instances ## Start instances
Start_all_instances 3 Start_all_instances 3
# Send test information from node 1
sleep 10
Send_Information
sleep 10
## List ip tables of nodes started ## List ip tables of nodes started
IP_Tables_after_Started 3 IP_Tables_after_Started 3
# #
@@ -112,3 +129,4 @@ Remove_all_test_files
## Kill all instances ## Kill all instances
Kill_all_instances Kill_all_instances

View File

@@ -1,40 +1,40 @@
package clientIPTable package clientIPTable
import ( import (
"errors" "errors"
"github.com/Akilan1999/p2p-rendering-computation/config" "github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/p2p" "github.com/Akilan1999/p2p-rendering-computation/p2p"
) )
func AddCustomInformationToIPTable(text string) error { func AddCustomInformationToIPTable(text string) error {
// Get config information // Get config information
Config, err := config.ConfigInit(nil, nil) Config, err := config.ConfigInit(nil, nil)
if err != nil { if err != nil {
return err return err
} }
// Get IPTable information // Get IPTable information
table, err := p2p.ReadIpTable() table, err := p2p.ReadIpTable()
if err != nil { if err != nil {
return err return err
} }
found := false found := false
for i, _ := range table.IpAddress { for i, _ := range table.IpAddress {
if table.IpAddress[i].Name == Config.MachineName { if table.IpAddress[i].Name == Config.MachineName {
table.IpAddress[i].CustomInformation = text table.IpAddress[i].CustomInformation = text
found = true found = true
} }
} }
if found { if found {
table.WriteIpTable() table.WriteIpTable()
// update IPTable after modified entry // update IPTable after modified entry
go UpdateIpTableListClient() UpdateIpTableListClient()
} else { } else {
return errors.New("start server with p2prc -s as the server is currently not running") return errors.New("start server with p2prc -s as the server is currently not running")
} }
return nil return nil
} }

View File

@@ -1,296 +1,297 @@
package p2p package p2p
import ( import (
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/Akilan1999/p2p-rendering-computation/config" "github.com/Akilan1999/p2p-rendering-computation/config"
"io/ioutil" "io/ioutil"
"net" "net"
"net/http" "net/http"
"os" "os"
"time" "time"
) )
// Get IP table Data // Get IP table Data
type IpAddresses struct { type IpAddresses struct {
IpAddress []IpAddress `json:"ip_address"` IpAddress []IpAddress `json:"ip_address"`
} }
type IpAddress struct { type IpAddress struct {
Name string `json:"Name"` Name string `json:"Name"`
MachineUsername string `json:"MachineUsername"` MachineUsername string `json:"MachineUsername"`
Ipv4 string `json:"IPV4"` Ipv4 string `json:"IPV4"`
Ipv6 string `json:"IPV6"` Ipv6 string `json:"IPV6"`
Latency time.Duration `json:"Latency"` Latency time.Duration `json:"Latency"`
Download float64 `json:"Download"` Download float64 `json:"Download"`
Upload float64 `json:"Upload"` Upload float64 `json:"Upload"`
ServerPort string `json:"ServerPort"` ServerPort string `json:"ServerPort"`
BareMetalSSHPort string `json:"BareMetalSSHPort"` BareMetalSSHPort string `json:"BareMetalSSHPort"`
NAT bool `json:"NAT"` NAT bool `json:"NAT"`
EscapeImplementation string `json:"EscapeImplementation"` EscapeImplementation string `json:"EscapeImplementation"`
ProxyServer bool `json:"ProxyServer"` ProxyServer bool `json:"ProxyServer"`
UnSafeMode bool `json:"UnSafeMode"` UnSafeMode bool `json:"UnSafeMode"`
PublicKey string `json:"PublicKey"` PublicKey string `json:"PublicKey"`
CustomInformation string `json:"CustomInformation"` CustomInformation string `json:"CustomInformation"`
//CustomInformationKey []byte `json:"CustomInformationKey"` //CustomInformationKey []byte `json:"CustomInformationKey"`
} }
type IP struct { type IP struct {
Query string Query string
} }
var Test = false var Test = false
// ReadIpTable Read data from Ip tables from json file // ReadIpTable Read data from Ip tables from json file
func ReadIpTable() (*IpAddresses, error) { func ReadIpTable() (*IpAddresses, error) {
// Get Path from config // Get Path from config
config, err := config.ConfigInit(nil, nil) config, err := config.ConfigInit(nil, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
jsonFile, err := os.Open(config.IPTable) jsonFile, err := os.Open(config.IPTable)
// if we os.Open returns an error then handle it // if we os.Open returns an error then handle it
if err != nil { if err != nil {
return nil, err return nil, err
} }
// defer the closing of our jsonFile so that we can parse it later on // defer the closing of our jsonFile so that we can parse it later on
defer jsonFile.Close() defer jsonFile.Close()
// read our opened xmlFile as a byte array. // read our opened xmlFile as a byte array.
byteValue, _ := ioutil.ReadAll(jsonFile) byteValue, _ := ioutil.ReadAll(jsonFile)
// we initialize our Users array // we initialize our Users array
var ipAddresses IpAddresses var ipAddresses IpAddresses
// we unmarshal our byteArray which contains our // we unmarshal our byteArray which contains our
// jsonFile's content into 'users' which we defined above // jsonFile's content into 'users' which we defined above
json.Unmarshal(byteValue, &ipAddresses) json.Unmarshal(byteValue, &ipAddresses)
var PublicIP IpAddress var PublicIP IpAddress
ipv6, err := GetCurrentIPV6() ipv6, err := GetCurrentIPV6()
if err != nil { if err != nil {
return nil, err return nil, err
} }
ip, err := CurrentPublicIP() ip, err := CurrentPublicIP()
if err != nil { if err != nil {
return nil, err return nil, err
} }
PublicIP.Ipv4 = ip PublicIP.Ipv4 = ip
PublicIP.Ipv6 = ipv6 PublicIP.Ipv6 = ipv6
PublicIP.ServerPort = config.ServerPort PublicIP.ServerPort = config.ServerPort
PublicIP.Name = config.MachineName PublicIP.Name = config.MachineName
PublicIP.NAT = config.BehindNAT PublicIP.NAT = config.BehindNAT
PublicIP.EscapeImplementation = "None" PublicIP.EscapeImplementation = "None"
// Updates current machine IP address to the IP table // Updates current machine IP address to the IP table
ipAddresses.IpAddress = append(ipAddresses.IpAddress, PublicIP) ipAddresses.IpAddress = append(ipAddresses.IpAddress, PublicIP)
//before writing to iptable ensures the duplicates are removed //before writing to iptable ensures the duplicates are removed
if err = ipAddresses.RemoveDuplicates(); err != nil { if err = ipAddresses.RemoveDuplicates(); err != nil {
return nil, err return nil, err
} }
return &ipAddresses, nil return &ipAddresses, nil
} }
// WriteIpTable Write to IP table json file // WriteIpTable Write to IP table json file
func (i *IpAddresses) WriteIpTable() error { func (i *IpAddresses) WriteIpTable() error {
//before writing to iptable ensures the duplicates are removed //before writing to iptable ensures the duplicates are removed
if err := i.RemoveDuplicates(); err != nil { if err := i.RemoveDuplicates(); err != nil {
return err return err
} }
file, err := json.MarshalIndent(i, "", " ") file, err := json.MarshalIndent(i, "", " ")
if err != nil { if err != nil {
return err return err
} }
// Get Path from config // Get Path from config
config, err := config.ConfigInit(nil, nil) config, err := config.ConfigInit(nil, nil)
if err != nil { if err != nil {
return err return err
} }
err = ioutil.WriteFile(config.IPTable, file, 0644) err = ioutil.WriteFile(config.IPTable, file, 0644)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
// PrintIpTable Print Ip table data for Cli // PrintIpTable Print Ip table data for Cli
func PrintIpTable() error { func PrintIpTable() error {
table, err := ReadIpTable() table, err := ReadIpTable()
// //
if err != nil { if err != nil {
return err return err
} }
// //
//for i := 0; i < len(table.IpAddress); i++ { //for i := 0; i < len(table.IpAddress); i++ {
// fmt.Printf("\nMachine Name: %s\nIP Address: %s\nIPV6: %s\nLatency: %s\nServerPort: %s\nbehindNAT: %s\nEscapeImplementation: %s\n-----------"+ // fmt.Printf("\nMachine Name: %s\nIP Address: %s\nIPV6: %s\nLatency: %s\nServerPort: %s\nbehindNAT: %s\nEscapeImplementation: %s\n-----------"+
// "-----------------\n", table.IpAddress[i].Name, table.IpAddress[i].Ipv4, table.IpAddress[i].Ipv6, // "-----------------\n", table.IpAddress[i].Name, table.IpAddress[i].Ipv4, table.IpAddress[i].Ipv6,
// table.IpAddress[i].Latency, table.IpAddress[i].ServerPort, table.IpAddress[i].NAT, table.IpAddress[i].EscapeImplementation) // table.IpAddress[i].Latency, table.IpAddress[i].ServerPort, table.IpAddress[i].NAT, table.IpAddress[i].EscapeImplementation)
//} //}
PrettyPrint(table) PrettyPrint(table)
return nil return nil
} }
// RemoveDuplicates This is a temporary fix current functions failing to remove // RemoveDuplicates This is a temporary fix current functions failing to remove
// Duplicate IP addresses from local IP table // Duplicate IP addresses from local IP table
func (table *IpAddresses) RemoveDuplicates() error { func (table *IpAddresses) RemoveDuplicates() error {
var NoDuplicates IpAddresses var NoDuplicates IpAddresses
for i, _ := range table.IpAddress { for i, _ := range table.IpAddress {
Exists := false Exists := false
for k := range NoDuplicates.IpAddress { for k := range NoDuplicates.IpAddress {
// Statements checked for // Statements checked for
// - duplicate IPV4 addresses [<IPV4>:<Port No>] // - duplicate IPV4 addresses [<IPV4>:<Port No>]
// - duplicate IPV6 addresses [<IPV6>] // - duplicate IPV6 addresses [<IPV6>]
// - Node is behind NAT and no escape implementation provided // - Node is behind NAT and no escape implementation provided
if (NoDuplicates.IpAddress[k].Ipv4 != "" && NoDuplicates.IpAddress[k].Ipv4 == table.IpAddress[i].Ipv4 && if (NoDuplicates.IpAddress[k].Ipv4 != "" && NoDuplicates.IpAddress[k].Ipv4 == table.IpAddress[i].Ipv4 &&
NoDuplicates.IpAddress[k].ServerPort == table.IpAddress[i].ServerPort) || NoDuplicates.IpAddress[k].ServerPort == table.IpAddress[i].ServerPort) ||
(NoDuplicates.IpAddress[k].Ipv6 != "" && NoDuplicates.IpAddress[k].Ipv6 == table.IpAddress[i].Ipv6) { (NoDuplicates.IpAddress[k].Ipv6 != "" && NoDuplicates.IpAddress[k].Ipv6 == table.IpAddress[i].Ipv6) {
Exists = true Exists = true
break break
} }
} }
if table.IpAddress[i].NAT && table.IpAddress[i].EscapeImplementation == "None" { if table.IpAddress[i].NAT && table.IpAddress[i].EscapeImplementation == "None" {
Exists = true Exists = true
} }
if Exists { if Exists {
continue continue
} }
NoDuplicates.IpAddress = append(NoDuplicates.IpAddress, table.IpAddress[i]) NoDuplicates.IpAddress = append(NoDuplicates.IpAddress, table.IpAddress[i])
} }
table.IpAddress = NoDuplicates.IpAddress table.IpAddress = NoDuplicates.IpAddress
return nil return nil
} }
// CurrentPublicIP Get Current Public IP address // CurrentPublicIP Get Current Public IP address
func CurrentPublicIP() (string, error) { func CurrentPublicIP() (string, error) {
// Get configs // Get configs
Config, err := config.ConfigInit(nil, nil) Config, err := config.ConfigInit(nil, nil)
if err != nil { if err != nil {
return "", err return "", err
} }
// If test mode is on then return local address // If test mode is on then return local address
if Config.Test { if Config.Test {
return "0.0.0.0", nil return "0.0.0.0", nil
} }
req, err := http.Get("http://ip-api.com/json/") req, err := http.Get("http://ip-api.com/json/")
if err != nil { if err != nil {
return "", err return "", err
} }
defer req.Body.Close() defer req.Body.Close()
body, err := ioutil.ReadAll(req.Body) body, err := ioutil.ReadAll(req.Body)
if err != nil { if err != nil {
return "", err return "", err
} }
var ip IP var ip IP
json.Unmarshal(body, &ip) json.Unmarshal(body, &ip)
return ip.Query, nil
return ip.Query, nil
} }
// GetCurrentIPV6 gets the current IPV6 address based on the interface // GetCurrentIPV6 gets the current IPV6 address based on the interface
// specified in the config file // specified in the config file
func GetCurrentIPV6() (string, error) { func GetCurrentIPV6() (string, error) {
Config, err := config.ConfigInit(nil, nil) Config, err := config.ConfigInit(nil, nil)
if err != nil { if err != nil {
return "", err return "", err
} }
// Fix in future release // Fix in future release
//byNameInterface, err := net.InterfaceByName(Config.NetworkInterface) //byNameInterface, err := net.InterfaceByName(Config.NetworkInterface)
//if err != nil { //if err != nil {
// return "",err // return "",err
//} //}
//addresses, err := byNameInterface.Addrs() //addresses, err := byNameInterface.Addrs()
//if err != nil { //if err != nil {
// return "",err // return "",err
//} //}
//if addresses[1].String() == "" { //if addresses[1].String() == "" {
// return "",errors.New("IPV6 address not detected") // return "",errors.New("IPV6 address not detected")
//} //}
//IP,_,err := net.ParseCIDR(addresses[Config.NetworkInterfaceIPV6Index].String()) //IP,_,err := net.ParseCIDR(addresses[Config.NetworkInterfaceIPV6Index].String())
//if err != nil { //if err != nil {
// return "",err // return "",err
//} //}
return Config.IPV6Address, nil return Config.IPV6Address, nil
} }
// ViewNetworkInterface This function is created to view the network interfaces available // ViewNetworkInterface This function is created to view the network interfaces available
func ViewNetworkInterface() error { func ViewNetworkInterface() error {
ifaces, err := net.Interfaces() ifaces, err := net.Interfaces()
if err != nil { if err != nil {
return err return err
} }
for _, i := range ifaces { for _, i := range ifaces {
addrs, err := i.Addrs() addrs, err := i.Addrs()
if err != nil { if err != nil {
return err return err
} }
for index, a := range addrs { for index, a := range addrs {
switch v := a.(type) { switch v := a.(type) {
case *net.IPAddr: case *net.IPAddr:
fmt.Printf("(%v) %v : %s (%s)\n", index, i.Name, v, v.IP.DefaultMask()) fmt.Printf("(%v) %v : %s (%s)\n", index, i.Name, v, v.IP.DefaultMask())
case *net.IPNet: case *net.IPNet:
fmt.Printf("(%v) %v : %s \n", index, i.Name, v) fmt.Printf("(%v) %v : %s \n", index, i.Name, v)
} }
} }
} }
return nil return nil
} }
// Ip4or6 Helper function to check if the IP address is IPV4 or // Ip4or6 Helper function to check if the IP address is IPV4 or
// IPV6 (https://socketloop.com/tutorials/golang-check-if-ip-address-is-version-4-or-6) // IPV6 (https://socketloop.com/tutorials/golang-check-if-ip-address-is-version-4-or-6)
func Ip4or6(s string) string { func Ip4or6(s string) string {
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
switch s[i] { switch s[i] {
case '.': case '.':
return "version 4" return "version 4"
case ':': case ':':
return "version 6" return "version 6"
} }
} }
return "version 6" return "version 6"
} }
func PrettyPrint(data interface{}) { func PrettyPrint(data interface{}) {
var p []byte var p []byte
// var err := error // var err := error
p, err := json.MarshalIndent(data, "", "\t") p, err := json.MarshalIndent(data, "", "\t")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
fmt.Printf("%s \n", p) fmt.Printf("%s \n", p)
} }
func GenerateHashSHA256(text string) []byte { func GenerateHashSHA256(text string) []byte {
h := sha256.New() h := sha256.New()
h.Write([]byte(text)) h.Write([]byte(text))
return h.Sum(nil) return h.Sum(nil)
} }
// ValidateHashSHA256 CustomInformationKey the text and check if the text and // ValidateHashSHA256 CustomInformationKey the text and check if the text and
@@ -299,12 +300,12 @@ func GenerateHashSHA256(text string) []byte {
// SHA256 is the current hashing algorthm // SHA256 is the current hashing algorthm
// used. // used.
func ValidateHashSHA256(text string, Hash []byte) bool { func ValidateHashSHA256(text string, Hash []byte) bool {
h := sha256.New() h := sha256.New()
h.Write([]byte(text)) h.Write([]byte(text))
textHash := h.Sum(nil) textHash := h.Sum(nil)
if bytes.Equal(textHash, Hash) { if bytes.Equal(textHash, Hash) {
return true return true
} }
return false return false
} }

View File

@@ -1,136 +1,137 @@
package p2p package p2p
import ( import (
"github.com/Akilan1999/p2p-rendering-computation/config" "github.com/Akilan1999/p2p-rendering-computation/config"
) )
// SpeedTest Runs a speed test and does updates IP tables accordingly // SpeedTest Runs a speed test and does updates IP tables accordingly
func (ip *IpAddresses) SpeedTest() error { func (ip *IpAddresses) SpeedTest() error {
//temp variable to store elements IP addresses and other information //temp variable to store elements IP addresses and other information
// of IP addresses that are pingable // of IP addresses that are pingable
var ActiveIP IpAddresses var ActiveIP IpAddresses
// Index to remove from struct // Index to remove from struct
for _, value := range ip.IpAddress { for _, value := range ip.IpAddress {
var err error var err error
//if len(ip.IpAddress) == 1 { //if len(ip.IpAddress) == 1 {
// i = 0 // i = 0
//} //}
// Ping Test // Ping Test
err = value.PingTest() err = value.PingTest()
if err != nil { if err != nil {
continue continue
} }
//Upload Speed Test //Upload Speed Test
//err = value.UploadSpeed() //err = value.UploadSpeed()
//if err != nil { //if err != nil {
// return err // return err
//} //}
// //
//err = value.DownloadSpeed() //err = value.DownloadSpeed()
//if err != nil { //if err != nil {
// return err // return err
//} //}
//Set value to the list //Set value to the list
ActiveIP.IpAddress = append(ActiveIP.IpAddress, value) ActiveIP.IpAddress = append(ActiveIP.IpAddress, value)
} }
ip.IpAddress = ActiveIP.IpAddress ip.IpAddress = ActiveIP.IpAddress
err := ip.WriteIpTable() err := ip.WriteIpTable()
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
// SpeedTestUpdatedIPTable Called when ip tables from httpclient/server is also passed on // SpeedTestUpdatedIPTable Called when ip tables from httpclient/server is also passed on
func (ip *IpAddresses) SpeedTestUpdatedIPTable() error { func (ip *IpAddresses) SpeedTestUpdatedIPTable() error {
Config, err := config.ConfigInit(nil, nil) Config, err := config.ConfigInit(nil, nil)
if err != nil { if err != nil {
return err return err
} }
targets, err := ReadIpTable() targets, err := ReadIpTable()
if err != nil { if err != nil {
return err return err
} }
// Checks if baremetal mode and unsafe mode // Checks if baremetal mode and unsafe mode
// is enabled. If it is enabled it adds the // is enabled. If it is enabled it adds the
// the propagated public key to the list. // the propagated public key to the list.
AddPublicKey := false AddPublicKey := false
if Config.BareMetal && Config.UnsafeMode { if Config.BareMetal && Config.UnsafeMode {
AddPublicKey = true AddPublicKey = true
} }
// To ensure struct has no duplicates IP addresses // To ensure struct has no duplicates IP addresses
//DoNotRead := targets //DoNotRead := targets
// Appends all IP addresses // Appends all IP addresses
for i, _ := range targets.IpAddress { for i, _ := range targets.IpAddress {
//To ensure that there are no duplicate IP addresses //To ensure that there are no duplicate IP addresses
Exists := false Exists := false
for k := range ip.IpAddress { for k := range ip.IpAddress {
if AddPublicKey && ip.IpAddress[k].PublicKey != "" { if AddPublicKey && ip.IpAddress[k].PublicKey != "" {
// This function call (AddAuthorisationKey) is inefficient but to be optimised later on. // This function call (AddAuthorisationKey) is inefficient but to be optimised later on.
// This is because when if the user is running on as unsafe mode the authorization file // This is because when if the user is running on as unsafe mode the authorization file
// is opened from the SSH directory and then iterates through every single SSH entry // is opened from the SSH directory and then iterates through every single SSH entry
// to find out if the SSH entry exists or not. This will incur multiple CPU cycles // to find out if the SSH entry exists or not. This will incur multiple CPU cycles
// for no reason. A better approach would be to have been to store the states on memory and only // for no reason. A better approach would be to have been to store the states on memory and only
// add when needed based on the memory location. This is something is to be discussed // add when needed based on the memory location. This is something is to be discussed
// and look upon later on. // and look upon later on.
AddAuthorisationKey(ip.IpAddress[k].PublicKey) AddAuthorisationKey(ip.IpAddress[k].PublicKey)
} }
// Checks if both the IPV4 addresses are the same or the IPV6 address is not targets.IpAddress[i].CustomInformation = ip.IpAddress[k].CustomInformation
// an empty string and IPV6 address are the same // Checks if both the IPV4 addresses are the same or the IPV6 address is not
if (ip.IpAddress[k].Ipv4 == targets.IpAddress[i].Ipv4 && targets.IpAddress[i].NAT) || (targets.IpAddress[i].Ipv6 != "" && ip.IpAddress[k].Ipv6 == targets.IpAddress[i].Ipv6) { // an empty string and IPV6 address are the same
Exists = true if (ip.IpAddress[k].Ipv4 == targets.IpAddress[i].Ipv4 && targets.IpAddress[i].NAT) || (targets.IpAddress[i].Ipv6 != "" && ip.IpAddress[k].Ipv6 == targets.IpAddress[i].Ipv6) {
break Exists = true
} break
} }
}
// If the struct exists then continues // If the struct exists then continues
if Exists { if Exists {
continue continue
} }
ip.IpAddress = append(ip.IpAddress, targets.IpAddress[i]) ip.IpAddress = append(ip.IpAddress, targets.IpAddress[i])
} }
err = ip.SpeedTest() err = ip.SpeedTest()
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
// LocalSpeedTestIpTable Runs speed test in iptables locally only // LocalSpeedTestIpTable Runs speed test in iptables locally only
func LocalSpeedTestIpTable() error { func LocalSpeedTestIpTable() error {
targets, err := ReadIpTable() targets, err := ReadIpTable()
if err != nil { if err != nil {
return err return err
} }
err = targets.SpeedTest() err = targets.SpeedTest()
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
// Helper function to remove element from an array of a struct // Helper function to remove element from an array of a struct

View File

@@ -1,479 +1,477 @@
package server package server
import ( import (
b64 "encoding/base64" b64 "encoding/base64"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable" "github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
"github.com/Akilan1999/p2p-rendering-computation/config" "github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/p2p" "github.com/Akilan1999/p2p-rendering-computation/p2p"
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp" "github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
"github.com/Akilan1999/p2p-rendering-computation/server/docker" "github.com/Akilan1999/p2p-rendering-computation/server/docker"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os/user" "os/user"
"strconv" "strconv"
"time" "time"
) )
type ReverseProxy struct { type ReverseProxy struct {
IPAddress string IPAddress string
Port string Port string
} }
// ReverseProxies Reverse to the map such as ReverseProxies[<domain nane>]ReverseProxy type // ReverseProxies Reverse to the map such as ReverseProxies[<domain nane>]ReverseProxy type
var ReverseProxies map[string]ReverseProxy var ReverseProxies map[string]ReverseProxy
func Server() (*gin.Engine, error) { func Server() (*gin.Engine, error) {
r := gin.Default() r := gin.Default()
// "The make function allocates and initializes a hash map data // "The make function allocates and initializes a hash map data
//structure and returns a map value that points to it. //structure and returns a map value that points to it.
//The specifics of that data structure are an implementation //The specifics of that data structure are an implementation
//detail of the runtime and are not specified by the language itself." //detail of the runtime and are not specified by the language itself."
// source: https://go.dev/blog/maps // source: https://go.dev/blog/maps
ReverseProxies = make(map[string]ReverseProxy) ReverseProxies = make(map[string]ReverseProxy)
//Get Server port based on the config file //Get Server port based on the config file
config, err := config.ConfigInit(nil, nil) config, err := config.ConfigInit(nil, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// update IPTable with new port and ip address and update ip table // update IPTable with new port and ip address and update ip table
var ProxyIpAddr p2p.IpAddress var ProxyIpAddr p2p.IpAddress
var lowestLatencyIpAddress p2p.IpAddress var lowestLatencyIpAddress p2p.IpAddress
// Gets default information of the server // Gets default information of the server
r.GET("/server_info", func(c *gin.Context) { r.GET("/server_info", func(c *gin.Context) {
c.JSON(http.StatusOK, ServerInfo()) c.JSON(http.StatusOK, ServerInfo())
}) })
// Speed test with 50 mbps // Speed test with 50 mbps
r.GET("/50", func(c *gin.Context) { r.GET("/50", func(c *gin.Context) {
// Get Path from config // Get Path from config
c.File(config.SpeedTestFile) c.File(config.SpeedTestFile)
}) })
// Route build to do a speed test // Route build to do a speed test
r.GET("/upload", func(c *gin.Context) { r.GET("/upload", func(c *gin.Context) {
file, _ := c.FormFile("file") file, _ := c.FormFile("file")
// Upload the file to specific dst. // Upload the file to specific dst.
// c.SaveUploadedFile(file, dst) // c.SaveUploadedFile(file, dst)
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename)) c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
}) })
//Gets Ip Table from server node //Gets Ip Table from server node
r.POST("/IpTable", func(c *gin.Context) { r.POST("/IpTable", func(c *gin.Context) {
// Getting IPV4 address of client // Getting IPV4 address of client
//var ClientHost p2p.IpAddress //var ClientHost p2p.IpAddress
// //
//if p2p.Ip4or6(c.ClientIP()) == "version 6" { //if p2p.Ip4or6(c.ClientIP()) == "version 6" {
// ClientHost.Ipv6 = c.ClientIP() // ClientHost.Ipv6 = c.ClientIP()
//} else { //} else {
// ClientHost.Ipv4 = c.ClientIP() // ClientHost.Ipv4 = c.ClientIP()
//} //}
// Variable to store IP table information // Variable to store IP table information
var IPTable p2p.IpAddresses var IPTable p2p.IpAddresses
// Receive file from POST request // Receive file from POST request
body, err := c.FormFile("json") body, err := c.FormFile("json")
if err != nil { if err != nil {
c.String(http.StatusOK, fmt.Sprint(err)) c.String(http.StatusOK, fmt.Sprint(err))
} }
// Open file // Open file
open, err := body.Open() open, err := body.Open()
if err != nil { if err != nil {
c.String(http.StatusOK, fmt.Sprint(err)) c.String(http.StatusOK, fmt.Sprint(err))
} }
// Open received file // Open received file
file, err := ioutil.ReadAll(open) file, err := ioutil.ReadAll(open)
if err != nil { if err != nil {
c.String(http.StatusOK, fmt.Sprint(err)) c.String(http.StatusOK, fmt.Sprint(err))
} }
json.Unmarshal(file, &IPTable) json.Unmarshal(file, &IPTable)
//Add Client IP address to IPTable struct //Add Client IP address to IPTable struct
//IPTable.IpAddress = append(IPTable.IpAddress, ClientHost) //IPTable.IpAddress = append(IPTable.IpAddress, ClientHost)
// Runs speed test to return only servers in the IP table pingable // Runs speed test to return only servers in the IP table pingable
err = IPTable.SpeedTestUpdatedIPTable() err = IPTable.SpeedTestUpdatedIPTable()
if err != nil { if err != nil {
c.String(http.StatusOK, fmt.Sprint(err)) c.String(http.StatusOK, fmt.Sprint(err))
} }
// Reads IP addresses from ip table // Reads IP addresses from ip table
IpAddresses, err := p2p.ReadIpTable() IpAddresses, err := p2p.ReadIpTable()
if err != nil { if err != nil {
c.String(http.StatusOK, fmt.Sprint(err)) c.String(http.StatusOK, fmt.Sprint(err))
} }
c.JSON(http.StatusOK, IpAddresses) c.JSON(http.StatusOK, IpAddresses)
}) })
// Starts docker container in server // Starts docker container in server
r.GET("/startcontainer", func(c *gin.Context) { r.GET("/startcontainer", func(c *gin.Context) {
// Get Number of ports to open and whether to use GPU or not // Get Number of ports to open and whether to use GPU or not
Ports := c.DefaultQuery("ports", "0") Ports := c.DefaultQuery("ports", "0")
GPU := c.DefaultQuery("GPU", "false") GPU := c.DefaultQuery("GPU", "false")
ContainerName := c.DefaultQuery("ContainerName", "") ContainerName := c.DefaultQuery("ContainerName", "")
BaseImage := c.DefaultQuery("BaseImage", "") BaseImage := c.DefaultQuery("BaseImage", "")
PublicKey := c.DefaultQuery("PublicKey", "") PublicKey := c.DefaultQuery("PublicKey", "")
var PortsInt int var PortsInt int
if PublicKey == "" { if PublicKey == "" {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", "Publickey not passed")) c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", "Publickey not passed"))
} }
PublicKeyDecoded, err := b64.StdEncoding.DecodeString(PublicKey) PublicKeyDecoded, err := b64.StdEncoding.DecodeString(PublicKey)
if err != nil { if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err)) c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
} }
// Convert Get Request value to int // Convert Get Request value to int
fmt.Sscanf(Ports, "%d", &PortsInt) fmt.Sscanf(Ports, "%d", &PortsInt)
fmt.Println(string(PublicKeyDecoded[:])) // Creates container and returns-back result to
// access container
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName, BaseImage, string(PublicKeyDecoded[:]))
// Creates container and returns-back result to if err != nil {
// access container c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName, BaseImage, string(PublicKeyDecoded[:])) }
if err != nil { // Ensures that FRP is triggered only if a proxy address is provided
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err)) if ProxyIpAddr.Ipv4 != "" && c.Request.Host != "localhost:"+config.ServerPort && c.Request.Host != "0.0.0.0:"+config.ServerPort {
} resp, err = frp.StartFRPCDockerContainer(ProxyIpAddr.Ipv4, lowestLatencyIpAddress.ServerPort, resp)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
}
// Ensures that FRP is triggered only if a proxy address is provided c.JSON(http.StatusOK, resp)
if ProxyIpAddr.Ipv4 != "" && c.Request.Host != "localhost:"+config.ServerPort && c.Request.Host != "0.0.0.0:"+config.ServerPort { })
resp, err = frp.StartFRPCDockerContainer(ProxyIpAddr.Ipv4, lowestLatencyIpAddress.ServerPort, resp)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
}
c.JSON(http.StatusOK, resp) //Remove container
}) r.GET("/RemoveContainer", func(c *gin.Context) {
ID := c.DefaultQuery("id", "0")
if err := docker.StopAndRemoveContainer(ID); err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
c.String(http.StatusOK, "success")
})
//Remove container //Show images available
r.GET("/RemoveContainer", func(c *gin.Context) { r.GET("/ShowImages", func(c *gin.Context) {
ID := c.DefaultQuery("id", "0") resp, err := docker.ViewAllContainers()
if err := docker.StopAndRemoveContainer(ID); err != nil { if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err)) c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
} }
c.String(http.StatusOK, "success") c.JSON(http.StatusOK, resp)
}) })
//Show images available // Request for port no from Server with address
r.GET("/ShowImages", func(c *gin.Context) { r.GET("/FRPPort", func(c *gin.Context) {
resp, err := docker.ViewAllContainers() port, err := frp.StartFRPProxyFromRandom()
if err != nil { if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err)) c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
} }
c.JSON(http.StatusOK, resp)
})
// Request for port no from Server with address c.String(http.StatusOK, strconv.Itoa(port))
r.GET("/FRPPort", func(c *gin.Context) { })
port, err := frp.StartFRPProxyFromRandom()
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
c.String(http.StatusOK, strconv.Itoa(port)) r.GET("/MAPPort", func(c *gin.Context) {
}) Ports := c.DefaultQuery("port", "0")
DomainName := c.DefaultQuery("domain_name", "")
url, _, err := MapPort(Ports, DomainName)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
r.GET("/MAPPort", func(c *gin.Context) { c.String(http.StatusOK, url)
Ports := c.DefaultQuery("port", "0") })
DomainName := c.DefaultQuery("domain_name", "")
url, _, err := MapPort(Ports, DomainName)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
c.String(http.StatusOK, url) r.GET("/AddProxy", func(c *gin.Context) {
}) DomainName := c.DefaultQuery("domain_name", "")
ip_address := c.DefaultQuery("ip_address", "")
Ports := c.DefaultQuery("port", "")
r.GET("/AddProxy", func(c *gin.Context) { if DomainName == "" || ip_address == "" || Ports == "" {
DomainName := c.DefaultQuery("domain_name", "") c.String(http.StatusInternalServerError, fmt.Sprintf("All get parameters npt provided"+
ip_address := c.DefaultQuery("ip_address", "") " do ensure domain_name, ip_Address and port no is provided"))
Ports := c.DefaultQuery("port", "") }
if DomainName == "" || ip_address == "" || Ports == "" { err := SaveRegistration(DomainName, ip_address+":"+Ports)
c.String(http.StatusInternalServerError, fmt.Sprintf("All get parameters npt provided"+ if err != nil {
" do ensure domain_name, ip_Address and port no is provided")) c.String(http.StatusInternalServerError, fmt.Sprintf(err.Error()))
} }
err := SaveRegistration(DomainName, ip_address+":"+Ports) //_, ok := ReverseProxies[DomainName]
if err != nil { //// To check if the subdomain entry exists
c.String(http.StatusInternalServerError, fmt.Sprintf(err.Error())) //if ok {
} // c.String(http.StatusInternalServerError, fmt.Sprintf("The domain entry already exists as a reverse"+
// " proxy entry"))
//}
//
//// added proxy as a map entry
//ReverseProxies[DomainName] = ReverseProxy{IPAddress: ip_address, Port: Ports}
c.String(http.StatusOK, "Sucess")
//_, ok := ReverseProxies[DomainName] })
//// To check if the subdomain entry exists
//if ok {
// c.String(http.StatusInternalServerError, fmt.Sprintf("The domain entry already exists as a reverse"+
// " proxy entry"))
//}
//
//// added proxy as a map entry
//ReverseProxies[DomainName] = ReverseProxy{IPAddress: ip_address, Port: Ports}
c.String(http.StatusOK, "Sucess")
}) //r.GET("/RemoveProxy", func(c *gin.Context) {
// DomainName := c.DefaultQuery("domain_name", "")
//
// _, ok := ReverseProxies[DomainName]
// if !ok {
// c.String(http.StatusInternalServerError, fmt.Sprintf("Domain name does exist in entries of proxies"))
// } else {
// delete(ReverseProxies, DomainName)
// }
//
//})
//r.GET("/RemoveProxy", func(c *gin.Context) { // If there is a proxy port specified
// DomainName := c.DefaultQuery("domain_name", "") // then starts the FRP server
// //if config.FRPServerPort != "0" {
// _, ok := ReverseProxies[DomainName] // go frp.StartFRPProxyFromRandom()
// if !ok { //}
// c.String(http.StatusInternalServerError, fmt.Sprintf("Domain name does exist in entries of proxies"))
// } else {
// delete(ReverseProxies, DomainName)
// }
//
//})
// If there is a proxy port specified // Remove nodes currently not pingable
// then starts the FRP server clientIPTable.RemoveOfflineNodes()
//if config.FRPServerPort != "0" {
// go frp.StartFRPProxyFromRandom()
//}
// Remove nodes currently not pingable table, err := p2p.ReadIpTable()
clientIPTable.RemoveOfflineNodes()
table, err := p2p.ReadIpTable() // TODO check if IPV6 or Proxy port is specified
// if not update current entry as proxy address
// with appropriate port on IP Table
if config.BehindNAT {
if err != nil {
return nil, err
}
// TODO check if IPV6 or Proxy port is specified var lowestLatency int64
// if not update current entry as proxy address // random large number
// with appropriate port on IP Table lowestLatency = 10000000
if config.BehindNAT {
if err != nil {
return nil, err
}
var lowestLatency int64 for i, _ := range table.IpAddress {
// random large number // Checks if the ping is the lowest and if the following node is acting as a proxy
lowestLatency = 10000000 //if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" {
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && !table.IpAddress[i].NAT {
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
lowestLatencyIpAddress = table.IpAddress[i]
}
}
for i, _ := range table.IpAddress { // If there is an identified node
// Checks if the ping is the lowest and if the following node is acting as a proxy if lowestLatency != 10000000 {
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" { serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && !table.IpAddress[i].NAT { if err != nil {
lowestLatency = table.IpAddress[i].Latency.Milliseconds() return nil, err
lowestLatencyIpAddress = table.IpAddress[i] }
} // Create 3 second delay to allow FRP server to start
} time.Sleep(1 * time.Second)
// Starts FRP as a client with
proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, serverPort, config.ServerPort, "")
if err != nil {
return nil, err
}
// If there is an identified node // updating with the current proxy address
if lowestLatency != 10000000 { ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort) ProxyIpAddr.ServerPort = proxyPort
if err != nil { ProxyIpAddr.Name = config.MachineName
return nil, err ProxyIpAddr.NAT = false
} ProxyIpAddr.ProxyServer = false
// Create 3 second delay to allow FRP server to start ProxyIpAddr.EscapeImplementation = "FRP"
time.Sleep(1 * time.Second)
// Starts FRP as a client with
proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, serverPort, config.ServerPort, "")
if err != nil {
return nil, err
}
// updating with the current proxy address if config.BareMetal {
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4 _, SSHPort, err := MapPort("22", "")
ProxyIpAddr.ServerPort = proxyPort if err != nil {
ProxyIpAddr.Name = config.MachineName return nil, err
ProxyIpAddr.NAT = false }
ProxyIpAddr.ProxyServer = false ProxyIpAddr.BareMetalSSHPort = SSHPort
ProxyIpAddr.EscapeImplementation = "FRP" }
if config.BareMetal { //ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey)
_, SSHPort, err := MapPort("22", "") // write information back to the IP Table
if err != nil { }
return nil, err
}
ProxyIpAddr.BareMetalSSHPort = SSHPort
}
//ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey) } else {
// write information back to the IP Table ProxyIpAddr.Ipv4, err = p2p.CurrentPublicIP()
} if err != nil {
fmt.Println(err)
}
} else { ProxyIpAddr.ServerPort = config.ServerPort
ProxyIpAddr.Ipv4, err = p2p.CurrentPublicIP() ProxyIpAddr.Name = config.MachineName
if err != nil { ProxyIpAddr.NAT = false
fmt.Println(err) if config.ProxyPort != "" {
} ProxyIpAddr.ProxyServer = true
}
ProxyIpAddr.EscapeImplementation = ""
if config.BareMetal {
ProxyIpAddr.BareMetalSSHPort = "22"
}
ProxyIpAddr.ServerPort = config.ServerPort }
ProxyIpAddr.Name = config.MachineName
ProxyIpAddr.NAT = false
if config.ProxyPort != "" {
ProxyIpAddr.ProxyServer = true
}
ProxyIpAddr.EscapeImplementation = ""
if config.BareMetal {
ProxyIpAddr.BareMetalSSHPort = "22"
}
} // Get machine username
currentUser, err := user.Current()
if err != nil {
return nil, err
}
// Add username p2prc binary is being run under
ProxyIpAddr.MachineUsername = currentUser.Username
ProxyIpAddr.UnSafeMode = config.UnsafeMode
// Adds the public key information to the IPTable
// improving transmission of IPTables without the
// entire public key is future work to be improved
// in the P2PRC protocol level (Improving by adding
// UDP with TCP reliability layer).
ProxyIpAddr.PublicKey, err = config.GetPublicKey()
// Get machine username if err != nil {
currentUser, err := user.Current() return nil, err
if err != nil { }
return nil, err
}
// Add username p2prc binary is being run under
ProxyIpAddr.MachineUsername = currentUser.Username
ProxyIpAddr.UnSafeMode = config.UnsafeMode
// Adds the public key information to the IPTable
// improving transmission of IPTables without the
// entire public key is future work to be improved
// in the P2PRC protocol level (Improving by adding
// UDP with TCP reliability layer).
ProxyIpAddr.PublicKey, err = config.GetPublicKey()
if err != nil { // append the following to the ip table
return nil, err table.IpAddress = append(table.IpAddress, ProxyIpAddr)
}
// append the following to the ip table // Writing results to the IPTable
table.IpAddress = append(table.IpAddress, ProxyIpAddr) err = table.WriteIpTable()
if err != nil {
return nil, err
}
// Writing results to the IPTable // update ip table
err = table.WriteIpTable() go func() error {
if err != nil { err := clientIPTable.UpdateIpTableListClient()
return nil, err if err != nil {
} fmt.Println(err)
return err
}
return nil
}()
// update ip table if config.ProxyPort != "" {
go func() error { go ProxyRun(config.ProxyPort)
err := clientIPTable.UpdateIpTableListClient() }
if err != nil {
fmt.Println(err)
return err
}
return nil
}()
if config.ProxyPort != "" { // Run gin server on the specified port
go ProxyRun(config.ProxyPort) go r.Run(":" + config.ServerPort)
}
// Run gin server on the specified port return r, nil
go r.Run(":" + config.ServerPort)
return r, nil
} }
func MapPort(port string, domainName string) (string, string, error) { func MapPort(port string, domainName string) (string, string, error) {
// if server address is provided to do call RESTAPI to remotely open port. // if server address is provided to do call RESTAPI to remotely open port.
//if serverAddress != "" { //if serverAddress != "" {
// requestURL := fmt.Sprintf("http://%v/MAPPort?port=%v&domain_name=%v", serverAddress, port, domainName) // requestURL := fmt.Sprintf("http://%v/MAPPort?port=%v&domain_name=%v", serverAddress, port, domainName)
// req, err := http.NewRequest(http.MethodGet, requestURL, nil) // req, err := http.NewRequest(http.MethodGet, requestURL, nil)
// if err != nil { // if err != nil {
// return "", "", err // return "", "", err
// } // }
// //
// res, err := http.DefaultClient.Do(req) // res, err := http.DefaultClient.Do(req)
// if err != nil { // if err != nil {
// return "", "", err // return "", "", err
// } // }
// //
// resBody, err := io.ReadAll(res.Body) // resBody, err := io.ReadAll(res.Body)
// if err != nil { // if err != nil {
// return "", "", err // return "", "", err
// } // }
// //
// _, Exposedport, err := net.SplitHostPort(string(resBody)) // _, Exposedport, err := net.SplitHostPort(string(resBody))
// if err != nil { // if err != nil {
// return "", "", err // return "", "", err
// } // }
// //
// return string(resBody), Exposedport, nil // return string(resBody), Exposedport, nil
//} //}
//Get Server port based on the config file //Get Server port based on the config file
config, err := config.ConfigInit(nil, nil) config, err := config.ConfigInit(nil, nil)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
// update IPTable with new port and ip address and update ip table // update IPTable with new port and ip address and update ip table
var ProxyIpAddr p2p.IpAddress var ProxyIpAddr p2p.IpAddress
var lowestLatencyIpAddress p2p.IpAddress var lowestLatencyIpAddress p2p.IpAddress
clientIPTable.RemoveOfflineNodes() clientIPTable.RemoveOfflineNodes()
table, err := p2p.ReadIpTable() table, err := p2p.ReadIpTable()
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
var lowestLatency int64 var lowestLatency int64
// random large number // random large number
lowestLatency = 10000000 lowestLatency = 10000000
for i, _ := range table.IpAddress { for i, _ := range table.IpAddress {
// Checks if the ping is the lowest and if the following node is acting as a proxy // Checks if the ping is the lowest and if the following node is acting as a proxy
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" { //if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" {
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && !table.IpAddress[i].NAT { if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && !table.IpAddress[i].NAT {
// Filter based on nodes with proxy enabled // Filter based on nodes with proxy enabled
if domainName != "" && table.IpAddress[i].ProxyServer { if domainName != "" && table.IpAddress[i].ProxyServer {
lowestLatency = table.IpAddress[i].Latency.Milliseconds() lowestLatency = table.IpAddress[i].Latency.Milliseconds()
lowestLatencyIpAddress = table.IpAddress[i] lowestLatencyIpAddress = table.IpAddress[i]
continue continue
} }
lowestLatency = table.IpAddress[i].Latency.Milliseconds() lowestLatency = table.IpAddress[i].Latency.Milliseconds()
lowestLatencyIpAddress = table.IpAddress[i] lowestLatencyIpAddress = table.IpAddress[i]
} }
} }
// If there is an identified node // If there is an identified node
if lowestLatency != 10000000 { if lowestLatency != 10000000 {
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort) serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
// Create 3 second delay to allow FRP server to start // Create 3 second delay to allow FRP server to start
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
// Starts FRP as a client with // Starts FRP as a client with
proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, serverPort, port, "") proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, serverPort, port, "")
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
// Doing the proxy mapping for the domain name // Doing the proxy mapping for the domain name
if domainName != "" { if domainName != "" {
fmt.Println("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort + "/AddProxy?port=" + proxyPort + "&domain_name=" + domainName + "&ip_address=" + lowestLatencyIpAddress.Ipv4) fmt.Println("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort + "/AddProxy?port=" + proxyPort + "&domain_name=" + domainName + "&ip_address=" + lowestLatencyIpAddress.Ipv4)
URL := "http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort + "/AddProxy?port=" + proxyPort + "&domain_name=" + domainName + "&ip_address=" + lowestLatencyIpAddress.Ipv4 URL := "http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort + "/AddProxy?port=" + proxyPort + "&domain_name=" + domainName + "&ip_address=" + lowestLatencyIpAddress.Ipv4
//} else { //} else {
// URL = "http://" + IP + ":" + serverPort + "/server_info" // URL = "http://" + IP + ":" + serverPort + "/server_info"
//} //}
http.Get(URL) http.Get(URL)
//SaveRegistration(domainName, lowestLatencyIpAddress.Ipv4+":"+proxyPort) //SaveRegistration(domainName, lowestLatencyIpAddress.Ipv4+":"+proxyPort)
} }
// updating with the current proxy address // updating with the current proxy address
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4 ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
ProxyIpAddr.ServerPort = proxyPort ProxyIpAddr.ServerPort = proxyPort
ProxyIpAddr.Name = config.MachineName ProxyIpAddr.Name = config.MachineName
ProxyIpAddr.NAT = false ProxyIpAddr.NAT = false
ProxyIpAddr.EscapeImplementation = "FRP" ProxyIpAddr.EscapeImplementation = "FRP"
//ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey) //ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey)
} else { } else {
return "", "", errors.New("proxy IP not found") return "", "", errors.New("proxy IP not found")
} }
return ProxyIpAddr.Ipv4 + ":" + ProxyIpAddr.ServerPort, ProxyIpAddr.ServerPort, nil return ProxyIpAddr.Ipv4 + ":" + ProxyIpAddr.ServerPort, ProxyIpAddr.ServerPort, nil
} }