base version working for reverse proxy

This commit is contained in:
2022-12-29 03:17:42 +00:00
parent 2138ee2d5d
commit ede9674a08
7 changed files with 655 additions and 634 deletions

View File

@@ -1,73 +1,74 @@
package config
import (
"github.com/spf13/viper"
"io"
"os"
"github.com/spf13/viper"
"io"
"os"
)
var (
defaultPath string
defaults = map[string]interface{}{}
configName = "config"
configType = "json"
configFile = "config.json"
configPaths []string
defaultEnvName = "P2PRC"
defaultPath string
defaults = map[string]interface{}{}
configName = "config"
configType = "json"
configFile = "config.json"
configPaths []string
defaultEnvName = "P2PRC"
)
type Config struct {
IPTable string
DockerContainers string
DefaultDockerFile string
SpeedTestFile string
IPV6Address string
PluginPath string
TrackContainersPath string
ServerPort string
GroupTrackContainersPath string
FRPServerPort string
//NetworkInterface string
//NetworkInterfaceIPV6Index int
IPTable string
DockerContainers string
DefaultDockerFile string
SpeedTestFile string
IPV6Address string
PluginPath string
TrackContainersPath string
ServerPort string
GroupTrackContainersPath string
FRPServerPort string
BehindNAT string
//NetworkInterface string
//NetworkInterfaceIPV6Index int
}
// Exists reports whether the named file or directory exists.
func fileExists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// Copy the src file to dst. Any existing file will be overwritten and will not
// copy file attributes.
// Source: https://stackoverflow.com/questions/21060945/simple-way-to-copy-a-file
func Copy(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, in)
if err != nil {
return err
}
return out.Close()
_, err = io.Copy(out, in)
if err != nil {
return err
}
return out.Close()
}
// GetPathP2PRC Getting P2PRC Directory from environment variable
func GetPathP2PRC() (string, error) {
curDir := os.Getenv(defaultEnvName)
return curDir + "/", nil
curDir := os.Getenv(defaultEnvName)
return curDir + "/", nil
}
// SetEnvName Sets the environment name
@@ -75,112 +76,113 @@ func GetPathP2PRC() (string, error) {
// your environment variable
// This is useful when extending the use case of P2PRC
func SetEnvName(EnvName string) error {
defaultEnvName = EnvName
// Handling error to be implemented only if needed
return nil
defaultEnvName = EnvName
// Handling error to be implemented only if needed
return nil
}
// GetCurrentPath Getting P2PRC Directory from environment variable
func GetCurrentPath() (string, error) {
curDir := os.Getenv("PWD")
return curDir + "/", nil
curDir := os.Getenv("PWD")
return curDir + "/", nil
}
// SetDefaults This function to be called only during a
// make install
func SetDefaults() error {
//Setting current directory to default path
defaultPath, err := GetPathP2PRC()
if err != nil {
return err
}
//Setting current directory to default path
defaultPath, err := GetPathP2PRC()
if err != nil {
return err
}
//Creates ip_table.json in the json directory
err = Copy("p2p/ip_table.json", "p2p/iptable/ip_table.json")
if err != nil {
return err
}
//Creates ip_table.json in the json directory
err = Copy("p2p/ip_table.json", "p2p/iptable/ip_table.json")
if err != nil {
return err
}
//Creates a copy of trackcontainers.json in the appropriate directory
err = Copy("client/trackcontainers.json", "client/trackcontainers/trackcontainers.json")
if err != nil {
return err
}
//Creates a copy of trackcontainers.json in the appropriate directory
err = Copy("client/trackcontainers.json", "client/trackcontainers/trackcontainers.json")
if err != nil {
return err
}
//Creates a copy of trackcontainers.json in the appropriate directory
err = Copy("client/grouptrackcontainers.json", "client/trackcontainers/grouptrackcontainers.json")
if err != nil {
return err
}
//Creates a copy of trackcontainers.json in the appropriate directory
err = Copy("client/grouptrackcontainers.json", "client/trackcontainers/grouptrackcontainers.json")
if err != nil {
return err
}
//Setting default paths for the config file
defaults["IPTable"] = defaultPath + "p2p/iptable/ip_table.json"
defaults["DefaultDockerFile"] = defaultPath + "server/docker/containers/docker-ubuntu-sshd/"
defaults["DockerContainers"] = defaultPath + "server/docker/containers/"
defaults["SpeedTestFile"] = defaultPath + "p2p/50.bin"
defaults["IPV6Address"] = ""
defaults["PluginPath"] = defaultPath + "plugin/deploy"
defaults["TrackContainersPath"] = defaultPath + "client/trackcontainers/trackcontainers.json"
defaults["GroupTrackContainersPath"] = defaultPath + "client/trackcontainers/grouptrackcontainers.json"
defaults["ServerPort"] = "8088"
defaults["FRPServerPort"] = "0"
//defaults["NetworkInterface"] = "wlp0s20f3"
//defaults["NetworkInterfaceIPV6Index"] = "2"
//Setting default paths for the config file
defaults["IPTable"] = defaultPath + "p2p/iptable/ip_table.json"
defaults["DefaultDockerFile"] = defaultPath + "server/docker/containers/docker-ubuntu-sshd/"
defaults["DockerContainers"] = defaultPath + "server/docker/containers/"
defaults["SpeedTestFile"] = defaultPath + "p2p/50.bin"
defaults["IPV6Address"] = ""
defaults["PluginPath"] = defaultPath + "plugin/deploy"
defaults["TrackContainersPath"] = defaultPath + "client/trackcontainers/trackcontainers.json"
defaults["GroupTrackContainersPath"] = defaultPath + "client/trackcontainers/grouptrackcontainers.json"
defaults["ServerPort"] = "8088"
defaults["FRPServerPort"] = "0"
defaults["BehindNAT"] = "True"
//defaults["NetworkInterface"] = "wlp0s20f3"
//defaults["NetworkInterfaceIPV6Index"] = "2"
//Paths to search for config file
configPaths = append(configPaths, defaultPath)
//Paths to search for config file
configPaths = append(configPaths, defaultPath)
if fileExists(defaultPath + "config.json") {
err := os.Remove(defaultPath + "config.json")
if err != nil {
return err
}
}
if fileExists(defaultPath + "config.json") {
err := os.Remove(defaultPath + "config.json")
if err != nil {
return err
}
}
//Calling configuration file
_, err = ConfigInit()
if err != nil {
return err
}
return nil
//Calling configuration file
_, err = ConfigInit()
if err != nil {
return err
}
return nil
}
func ConfigInit() (*Config, error) {
//Setting current directory to default path
defaultPath, err := GetPathP2PRC()
if err != nil {
return nil, err
}
//Paths to search for config file
configPaths = append(configPaths, defaultPath)
//Setting current directory to default path
defaultPath, err := GetPathP2PRC()
if err != nil {
return nil, err
}
//Paths to search for config file
configPaths = append(configPaths, defaultPath)
//Add all possible configurations paths
for _, v := range configPaths {
viper.AddConfigPath(v)
}
//Add all possible configurations paths
for _, v := range configPaths {
viper.AddConfigPath(v)
}
//Read config file
if err := viper.ReadInConfig(); err != nil {
// If the error thrown is config file not found
//Sets default configuration to viper
for k, v := range defaults {
viper.SetDefault(k, v)
}
viper.SetConfigName(configName)
viper.SetConfigFile(configFile)
viper.SetConfigType(configType)
//Read config file
if err := viper.ReadInConfig(); err != nil {
// If the error thrown is config file not found
//Sets default configuration to viper
for k, v := range defaults {
viper.SetDefault(k, v)
}
viper.SetConfigName(configName)
viper.SetConfigFile(configFile)
viper.SetConfigType(configType)
if err = viper.WriteConfig(); err != nil {
return nil, err
}
}
if err = viper.WriteConfig(); err != nil {
return nil, err
}
}
// Adds configuration to the struct
var config Config
if err := viper.Unmarshal(&config); err != nil {
return nil, err
}
// Adds configuration to the struct
var config Config
if err := viper.Unmarshal(&config); err != nil {
return nil, err
}
return &config, nil
return &config, nil
}

View File

@@ -1,134 +1,140 @@
package frp
import (
"git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker"
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/pkg/config"
"math/rand"
"strconv"
"git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker"
"github.com/fatedier/frp/client"
"github.com/fatedier/frp/pkg/config"
"math/rand"
"strconv"
)
// Client This struct stores
// client information with server
// proxy connected
type Client struct {
Name string
Server *Server
ClientMappings []ClientMapping
Name string
Server *Server
ClientMappings []ClientMapping
}
// ClientMapping Stores client mapping ports
// to proxy server
type ClientMapping struct {
LocalIP string
LocalPort int
RemotePort int
LocalIP string
LocalPort int
RemotePort int
}
// StartFRPClientForServer Starts Server using FRP server
// returns back a port
func StartFRPClientForServer(ipaddress string, port string) (string, error) {
// Setup server information
var s Server
s.address = ipaddress
// convert port to int
portInt, err := strconv.Atoi(port)
if err != nil {
return "", err
}
s.port = portInt
func StartFRPClientForServer(ipaddress string, port string, localport string) (string, error) {
// Setup server information
var s Server
s.address = ipaddress
// convert port to int
portInt, err := strconv.Atoi(port)
if err != nil {
return "", err
}
s.port = portInt
// Setup client information
var c Client
c.Name = "ServerPort"
c.Server = &s
// Setup client information
var c Client
c.Name = "ServerPort"
c.Server = &s
//random port
randPort := rangeIn(10000, 99999)
c.ClientMappings = []ClientMapping{
{
LocalIP: ipaddress,
LocalPort: randPort,
RemotePort: randPort,
},
}
// converts localport to int
portInt, err = strconv.Atoi(localport)
if err != nil {
return "", err
}
// Start client server
go c.StartFRPClient()
//random port
randPort := rangeIn(10000, 99999)
c.ClientMappings = []ClientMapping{
{
LocalIP: ipaddress,
LocalPort: portInt,
RemotePort: randPort,
},
}
return strconv.Itoa(randPort), nil
// Start client server
go c.StartFRPClient()
return strconv.Itoa(randPort), nil
}
func StartFRPCDockerContainer(ipaddress string, port string, docker *docker.DockerVM) error {
// Setup server information
var s Server
s.address = ipaddress
// convert port to int
portInt, err := strconv.Atoi(port)
if err != nil {
return err
}
s.port = portInt
// Setup server information
var s Server
s.address = ipaddress
// convert port to int
portInt, err := strconv.Atoi(port)
if err != nil {
return err
}
s.port = portInt
// Setup client information
var c Client
c.Name = "ServerPort"
c.Server = &s
// Setup client information
var c Client
c.Name = "ServerPort"
c.Server = &s
// set client mapping
var clientMappings []ClientMapping
for i, _ := range docker.Ports.PortSet {
// Set client mapping
var clientMapping ClientMapping
portMap := docker.Ports.PortSet[i].ExternalPort
clientMapping.LocalPort = portMap
clientMapping.RemotePort = portMap
// Append to array
clientMappings = append(clientMappings, clientMapping)
}
// set client mapping
var clientMappings []ClientMapping
for i, _ := range docker.Ports.PortSet {
// Set client mapping
var clientMapping ClientMapping
portMap := docker.Ports.PortSet[i].ExternalPort
clientMapping.LocalPort = portMap
clientMapping.RemotePort = portMap
// Append to array
clientMappings = append(clientMappings, clientMapping)
}
// Start client server
go c.StartFRPClient()
// Start client server
go c.StartFRPClient()
return nil
return nil
}
// StartFRPClient Starts FRP client
func (c *Client) StartFRPClient() error {
cfg := config.GetDefaultClientConf()
cfg := config.GetDefaultClientConf()
var proxyConfs map[string]config.ProxyConf
var visitorCfgs map[string]config.VisitorConf
var proxyConfs map[string]config.ProxyConf
var visitorCfgs map[string]config.VisitorConf
proxyConfs = make(map[string]config.ProxyConf)
proxyConfs = make(map[string]config.ProxyConf)
cfg.ServerAddr = c.Server.address
cfg.ServerPort = c.Server.port
cfg.ServerAddr = c.Server.address
cfg.ServerPort = c.Server.port
for i, _ := range c.ClientMappings {
var tcpcnf config.TCPProxyConf
tcpcnf.LocalIP = c.ClientMappings[i].LocalIP
tcpcnf.LocalPort = c.ClientMappings[i].LocalPort
tcpcnf.RemotePort = c.ClientMappings[i].RemotePort
for i, _ := range c.ClientMappings {
var tcpcnf config.TCPProxyConf
tcpcnf.LocalIP = c.ClientMappings[i].LocalIP
tcpcnf.LocalPort = c.ClientMappings[i].LocalPort
tcpcnf.RemotePort = c.ClientMappings[i].RemotePort
proxyConfs[tcpcnf.ProxyName] = &tcpcnf
}
proxyConfs[tcpcnf.ProxyName] = &tcpcnf
}
cli, err := client.NewService(cfg, proxyConfs, visitorCfgs, "")
if err != nil {
return err
}
cli, err := client.NewService(cfg, proxyConfs, visitorCfgs, "")
if err != nil {
return err
}
cli.Run()
cli.Run()
return nil
return nil
}
// helper function to generate random
// number in a certain range
func rangeIn(low, hi int) int {
return low + rand.Intn(hi-low)
return low + rand.Intn(hi-low)
}

View File

@@ -1,12 +1,13 @@
{
"ip_address": [
{
"ipv4": "139.162.246.221",
"ipv4": "64.227.168.102",
"ipv6": "",
"latency": 0,
"download": 0,
"upload": 0,
"serverport": "8088"
"serverport": "8088",
"proxyport": "7000"
}
]
}
}

View File

@@ -1,243 +1,255 @@
package p2p
import (
"encoding/json"
"fmt"
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
"io/ioutil"
"net"
"net/http"
"os"
"time"
"encoding/json"
"fmt"
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
"io/ioutil"
"net"
"net/http"
"os"
"time"
)
// Get IP table Data
type IpAddresses struct {
IpAddress []IpAddress `json:"ip_address"`
IpAddress []IpAddress `json:"ip_address"`
}
type IpAddress struct {
Ipv4 string `json:"ipv4"`
Ipv6 string `json:"ipv6"`
Latency time.Duration `json:"latency"`
Download float64 `json:"download"`
Upload float64 `json:"upload"`
ServerPort string `json:"serverport"`
ProxyPort string `json:"proxyport"`
Ipv4 string `json:"ipv4"`
Ipv6 string `json:"ipv6"`
Latency time.Duration `json:"latency"`
Download float64 `json:"download"`
Upload float64 `json:"upload"`
ServerPort string `json:"serverport"`
ProxyPort string `json:"proxyport"`
}
type IP struct {
Query string
Query string
}
// ReadIpTable 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.IPTable)
// if we os.Open returns an error then handle it
if err != nil {
return nil, err
}
// Get Path from config
config, err := config.ConfigInit()
if err != nil {
return nil, err
}
jsonFile, err := os.Open(config.IPTable)
// 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()
// 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)
// read our opened xmlFile as a byte array.
byteValue, _ := ioutil.ReadAll(jsonFile)
// we initialize our Users array
var ipAddresses IpAddresses
// 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)
// we unmarshal our byteArray which contains our
// jsonFile's content into 'users' which we defined above
json.Unmarshal(byteValue, &ipAddresses)
var PublicIP IpAddress
var PublicIP IpAddress
ipv6, err := GetCurrentIPV6()
if err != nil {
return nil, err
}
ipv6, err := GetCurrentIPV6()
if err != nil {
return nil, err
}
ip, err := CurrentPublicIP()
if err != nil {
return nil, err
}
PublicIP.Ipv4 = ip
PublicIP.Ipv6 = ipv6
PublicIP.ServerPort = config.ServerPort
if config.FRPServerPort != "0" {
PublicIP.ProxyPort = config.FRPServerPort
}
ip, err := CurrentPublicIP()
if err != nil {
return nil, err
}
PublicIP.Ipv4 = ip
PublicIP.Ipv6 = ipv6
PublicIP.ServerPort = config.ServerPort
if config.FRPServerPort != "0" {
PublicIP.ProxyPort = config.FRPServerPort
}
// Updates current machine IP address to the IP table
ipAddresses.IpAddress = append(ipAddresses.IpAddress, PublicIP)
// Updates current machine IP address to the IP table
ipAddresses.IpAddress = append(ipAddresses.IpAddress, PublicIP)
//before writing to iptable ensures the duplicates are removed
if err = ipAddresses.RemoveDuplicates(); err != nil {
return nil, err
}
//before writing to iptable ensures the duplicates are removed
if err = ipAddresses.RemoveDuplicates(); err != nil {
return nil, err
}
return &ipAddresses, nil
return &ipAddresses, nil
}
// WriteIpTable Write to IP table json file
func (i *IpAddresses) WriteIpTable() error {
//before writing to iptable ensures the duplicates are removed
if err := i.RemoveDuplicates(); err != nil {
return err
}
//before writing to iptable ensures the duplicates are removed
if err := i.RemoveDuplicates(); err != nil {
return err
}
file, err := json.MarshalIndent(i, "", " ")
if err != nil {
return err
}
file, err := json.MarshalIndent(i, "", " ")
if err != nil {
return err
}
// Get Path from config
config, err := config.ConfigInit()
if err != nil {
return err
}
// Get Path from config
config, err := config.ConfigInit()
if err != nil {
return err
}
err = ioutil.WriteFile(config.IPTable, file, 0644)
if err != nil {
return err
}
err = ioutil.WriteFile(config.IPTable, file, 0644)
if err != nil {
return err
}
return nil
return nil
}
// PrintIpTable Print Ip table data for Cli
func PrintIpTable() error {
table, err := ReadIpTable()
table, err := ReadIpTable()
if err != nil {
return err
}
if err != nil {
return err
}
for i := 0; i < len(table.IpAddress); i++ {
fmt.Printf("\nIP Address: %s\nIPV6: %s\nLatency: %s\nServerPort: %s\n-----------"+
"-----------------\n", table.IpAddress[i].Ipv4, table.IpAddress[i].Ipv6,
table.IpAddress[i].Latency, table.IpAddress[i].ServerPort)
}
//for i := 0; i < len(table.IpAddress); i++ {
// fmt.Printf("\nIP Address: %s\nIPV6: %s\nLatency: %s\nServerPort: %s\n-----------"+
// "-----------------\n", table.IpAddress[i].Ipv4, table.IpAddress[i].Ipv6,
// table.IpAddress[i].Latency, table.IpAddress[i].ServerPort)
//}
PrettyPrint(table)
return nil
return nil
}
// RemoveDuplicates This is a temporary fix current functions failing to remove
// Duplicate IP addresses from local IP table
func (table *IpAddresses) RemoveDuplicates() error {
var NoDuplicates IpAddresses
for i, _ := range table.IpAddress {
Exists := false
for k := range NoDuplicates.IpAddress {
if (NoDuplicates.IpAddress[k].Ipv4 != "" && NoDuplicates.IpAddress[k].Ipv4 == table.IpAddress[i].Ipv4) || (NoDuplicates.IpAddress[k].Ipv6 != "" && NoDuplicates.IpAddress[k].Ipv6 == table.IpAddress[i].Ipv6) {
if NoDuplicates.IpAddress[k].ProxyPort == "0" {
Exists = true
break
}
}
}
if Exists {
continue
}
NoDuplicates.IpAddress = append(NoDuplicates.IpAddress, table.IpAddress[i])
}
var NoDuplicates IpAddresses
for i, _ := range table.IpAddress {
Exists := false
for k := range NoDuplicates.IpAddress {
if (NoDuplicates.IpAddress[k].Ipv4 != "" && NoDuplicates.IpAddress[k].Ipv4 == table.IpAddress[i].Ipv4) || (NoDuplicates.IpAddress[k].Ipv6 != "" && NoDuplicates.IpAddress[k].Ipv6 == table.IpAddress[i].Ipv6) {
if NoDuplicates.IpAddress[k].ProxyPort == "0" {
Exists = true
break
}
}
}
if Exists {
continue
}
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
func CurrentPublicIP() (string, error) {
req, err := http.Get("http://ip-api.com/json/")
if err != nil {
return "", err
}
defer req.Body.Close()
req, err := http.Get("http://ip-api.com/json/")
if err != nil {
return "", err
}
defer req.Body.Close()
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return "", err
}
body, err := ioutil.ReadAll(req.Body)
if err != nil {
return "", err
}
var ip IP
json.Unmarshal(body, &ip)
var ip IP
json.Unmarshal(body, &ip)
return ip.Query, nil
return ip.Query, nil
}
// GetCurrentIPV6 gets the current IPV6 address based on the interface
// specified in the config file
func GetCurrentIPV6() (string, error) {
Config, err := config.ConfigInit()
if err != nil {
return "", err
}
Config, err := config.ConfigInit()
if err != nil {
return "", err
}
// Fix in future release
//byNameInterface, err := net.InterfaceByName(Config.NetworkInterface)
//if err != nil {
// return "",err
//}
//addresses, err := byNameInterface.Addrs()
//if err != nil {
// return "",err
//}
//if addresses[1].String() == "" {
// return "",errors.New("IPV6 address not detected")
//}
//IP,_,err := net.ParseCIDR(addresses[Config.NetworkInterfaceIPV6Index].String())
//if err != nil {
// return "",err
//}
// Fix in future release
//byNameInterface, err := net.InterfaceByName(Config.NetworkInterface)
//if err != nil {
// return "",err
//}
//addresses, err := byNameInterface.Addrs()
//if err != nil {
// return "",err
//}
//if addresses[1].String() == "" {
// return "",errors.New("IPV6 address not detected")
//}
//IP,_,err := net.ParseCIDR(addresses[Config.NetworkInterfaceIPV6Index].String())
//if err != nil {
// return "",err
//}
return Config.IPV6Address, nil
return Config.IPV6Address, nil
}
// ViewNetworkInterface This function is created to view the network interfaces available
func ViewNetworkInterface() error {
ifaces, err := net.Interfaces()
if err != nil {
return err
}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
return err
}
for index, a := range addrs {
switch v := a.(type) {
case *net.IPAddr:
fmt.Printf("(%v) %v : %s (%s)\n", index, i.Name, v, v.IP.DefaultMask())
ifaces, err := net.Interfaces()
if err != nil {
return err
}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
return err
}
for index, a := range addrs {
switch v := a.(type) {
case *net.IPAddr:
fmt.Printf("(%v) %v : %s (%s)\n", index, i.Name, v, v.IP.DefaultMask())
case *net.IPNet:
fmt.Printf("(%v) %v : %s \n", index, i.Name, v)
}
case *net.IPNet:
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
//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 {
for i := 0; i < len(s); i++ {
switch s[i] {
case '.':
return "version 4"
case ':':
return "version 6"
}
}
return "version 6"
for i := 0; i < len(s); i++ {
switch s[i] {
case '.':
return "version 4"
case ':':
return "version 6"
}
}
return "version 6"
}
func PrettyPrint(data interface{}) {
var p []byte
// var err := error
p, err := json.MarshalIndent(data, "", "\t")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%s \n", p)
}

View File

@@ -3,106 +3,106 @@ package p2p
// SpeedTest Runs a speed test and does updates IP tables accordingly
func (ip *IpAddresses) SpeedTest() error {
//temp variable to store elements IP addresses and other information
// of IP addresses that are pingable
var ActiveIP IpAddresses
//temp variable to store elements IP addresses and other information
// of IP addresses that are pingable
var ActiveIP IpAddresses
// Index to remove from struct
for _, value := range ip.IpAddress {
// Index to remove from struct
for _, value := range ip.IpAddress {
var err error
//if len(ip.IpAddress) == 1 {
// i = 0
//}
var err error
//if len(ip.IpAddress) == 1 {
// i = 0
//}
// Ping Test
err = value.PingTest()
// Ping Test
err = value.PingTest()
if err != nil {
continue
}
if err != nil {
continue
}
//Upload Speed Test
//err = value.UploadSpeed()
//if err != nil {
// return err
//}
//
//err = value.DownloadSpeed()
//if err != nil {
// return err
//}
//Upload Speed Test
//err = value.UploadSpeed()
//if err != nil {
// return err
//}
//
//err = value.DownloadSpeed()
//if err != nil {
// 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()
if err != nil {
return err
}
err := ip.WriteIpTable()
if err != nil {
return err
}
return nil
return nil
}
// SpeedTestUpdatedIPTable Called when ip tables from httpclient/server is also passed on
func (ip *IpAddresses) SpeedTestUpdatedIPTable() error {
targets, err := ReadIpTable()
if err != nil {
return err
}
targets, err := ReadIpTable()
if err != nil {
return err
}
// To ensure struct has no duplicates IP addresses
//DoNotRead := targets
// To ensure struct has no duplicates IP addresses
//DoNotRead := targets
// Appends all IP addresses
for i, _ := range targets.IpAddress {
// Appends all IP addresses
for i, _ := range targets.IpAddress {
// To ensure that there are no duplicate IP addresses
//Exists := false
//for k := range ip.IpAddress {
// // Checks if both the IPV4 addresses are the same or the IPV6 address is not
// // an empty string and IPV6 address are the same
// if ip.IpAddress[k].Ipv4 == targets.IpAddress[i].Ipv4 || (targets.IpAddress[i].Ipv6 != "" && ip.IpAddress[k].Ipv6 == targets.IpAddress[i].Ipv6) {
// Exists = true
// break
// }
//}
//
//// If the struct exists then continues
//if Exists {
// continue
//}
//To ensure that there are no duplicate IP addresses
Exists := false
for k := range ip.IpAddress {
// Checks if both the IPV4 addresses are the same or the IPV6 address is not
// an empty string and IPV6 address are the same
if (ip.IpAddress[k].Ipv4 == targets.IpAddress[i].Ipv4 && targets.IpAddress[i].ProxyPort == "0") || (targets.IpAddress[i].Ipv6 != "" && ip.IpAddress[k].Ipv6 == targets.IpAddress[i].Ipv6 && targets.IpAddress[i].ProxyPort == "0") {
Exists = true
break
}
}
ip.IpAddress = append(ip.IpAddress, targets.IpAddress[i])
}
// If the struct exists then continues
if Exists {
continue
}
err = ip.SpeedTest()
ip.IpAddress = append(ip.IpAddress, targets.IpAddress[i])
}
if err != nil {
return err
}
err = ip.SpeedTest()
return nil
if err != nil {
return err
}
return nil
}
// LocalSpeedTestIpTable Runs speed test in iptables locally only
func LocalSpeedTestIpTable() error {
targets, err := ReadIpTable()
if err != nil {
return err
}
targets, err := ReadIpTable()
if err != nil {
return err
}
err = targets.SpeedTest()
if err != nil {
return err
}
err = targets.SpeedTest()
if err != nil {
return err
}
return nil
return nil
}
// Helper function to remove element from an array of a struct

View File

@@ -2,6 +2,7 @@ package p2p
import (
"bytes"
"errors"
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
"io"
"io/ioutil"
@@ -12,8 +13,8 @@ import (
"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 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 httpclient = http.Client{}
// DownloadTest executes the test to measure download speed
@@ -78,7 +79,7 @@ var httpclient = http.Client{}
//}
// Download Speed
func (s *IpAddress)DownloadSpeed() error {
func (s *IpAddress) DownloadSpeed() error {
start := time.Now()
resp, err := httpclient.Get("http://" + s.Ipv4 + ":8088/50")
if err != nil {
@@ -89,11 +90,11 @@ func (s *IpAddress)DownloadSpeed() error {
t := time.Since(start)
//fmt.Println(s.Seconds())
// size * time (seconds)
s.Download = (50/t.Seconds())*8
return nil
s.Download = (50 / t.Seconds()) * 8
return nil
}
func (s *IpAddress)UploadSpeed() error {
func (s *IpAddress) UploadSpeed() error {
start := time.Now()
// Get upload file path from config file
@@ -103,9 +104,9 @@ func (s *IpAddress)UploadSpeed() error {
return err
}
b, w := createMultipartFormData("file",config.SpeedTestFile)
b, w := createMultipartFormData("file", config.SpeedTestFile)
req, err := http.NewRequest("GET", "http://" + s.Ipv4 + ":" + s.ServerPort + "/upload", &b)
req, err := http.NewRequest("GET", "http://"+s.Ipv4+":"+s.ServerPort+"/upload", &b)
if err != nil {
return err
}
@@ -116,12 +117,12 @@ func (s *IpAddress)UploadSpeed() error {
t := time.Since(start)
//fmt.Println(s.Seconds())
// size * time (seconds)
s.Upload = (50/t.Seconds())*8
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
// 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
@@ -142,7 +143,7 @@ func createMultipartFormData(fieldName, fileName string) (bytes.Buffer, *multipa
func mustOpen(f string) *os.File {
r, err := os.Open(f)
if err != nil {
log.Fatalf("Error with mustOpen: %v",err)
log.Fatalf("Error with mustOpen: %v", err)
}
return r
}
@@ -163,8 +164,8 @@ func (s *IpAddress) PingTest() error {
sTime := time.Now()
resp, err := http.Get(pingURL)
fTime := time.Now()
if err != nil {
return err
if err != nil || resp.StatusCode != 200 {
return errors.New("Node not found")
}
if fTime.Sub(sTime) < l {
l = fTime.Sub(sTime)
@@ -176,4 +177,3 @@ func (s *IpAddress) PingTest() error {
return nil
}

View File

@@ -1,208 +1,208 @@
package server
import (
"encoding/json"
"fmt"
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
"git.sr.ht/~akilan1999/p2p-rendering-computation/p2p"
"git.sr.ht/~akilan1999/p2p-rendering-computation/p2p/frp"
"git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker"
"github.com/gin-gonic/gin"
"io/ioutil"
"net/http"
"encoding/json"
"fmt"
"git.sr.ht/~akilan1999/p2p-rendering-computation/config"
"git.sr.ht/~akilan1999/p2p-rendering-computation/p2p"
"git.sr.ht/~akilan1999/p2p-rendering-computation/p2p/frp"
"git.sr.ht/~akilan1999/p2p-rendering-computation/server/docker"
"github.com/gin-gonic/gin"
"io/ioutil"
"net/http"
)
func Server() error {
r := gin.Default()
r := gin.Default()
// update IPTable with new port and ip address and update ip table
var ProxyIpAddr p2p.IpAddress
// update IPTable with new port and ip address and update ip table
var ProxyIpAddr p2p.IpAddress
// Gets default information of the server
r.GET("/server_info", func(c *gin.Context) {
c.JSON(http.StatusOK, ServerInfo())
})
// Gets default information of the server
r.GET("/server_info", func(c *gin.Context) {
c.JSON(http.StatusOK, ServerInfo())
})
// Speed test with 50 mbps
r.GET("/50", func(c *gin.Context) {
// Get Path from config
config, err := config.ConfigInit()
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
c.File(config.SpeedTestFile)
})
// Speed test with 50 mbps
r.GET("/50", func(c *gin.Context) {
// Get Path from config
config, err := config.ConfigInit()
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
c.File(config.SpeedTestFile)
})
// Route build to do a speed test
r.GET("/upload", func(c *gin.Context) {
file, _ := c.FormFile("file")
// Route build to do a speed test
r.GET("/upload", func(c *gin.Context) {
file, _ := c.FormFile("file")
// Upload the file to specific dst.
// c.SaveUploadedFile(file, dst)
// Upload the file to specific 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
r.POST("/IpTable", func(c *gin.Context) {
// Getting IPV4 address of client
var ClientHost p2p.IpAddress
//Gets Ip Table from server node
r.POST("/IpTable", func(c *gin.Context) {
// Getting IPV4 address of client
var ClientHost p2p.IpAddress
if p2p.Ip4or6(c.ClientIP()) == "version 6" {
ClientHost.Ipv6 = c.ClientIP()
} else {
ClientHost.Ipv4 = c.ClientIP()
}
if p2p.Ip4or6(c.ClientIP()) == "version 6" {
ClientHost.Ipv6 = c.ClientIP()
} else {
ClientHost.Ipv4 = c.ClientIP()
}
// Variable to store IP table information
var IPTable p2p.IpAddresses
// Variable to store IP table information
var IPTable p2p.IpAddresses
// Receive file from POST request
body, err := c.FormFile("json")
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
// Receive file from POST request
body, err := c.FormFile("json")
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
// Open file
open, err := body.Open()
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
// Open file
open, err := body.Open()
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
// Open received file
file, err := ioutil.ReadAll(open)
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
// Open received file
file, err := ioutil.ReadAll(open)
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
json.Unmarshal(file, &IPTable)
json.Unmarshal(file, &IPTable)
//Add Client IP address to IPTable struct
IPTable.IpAddress = append(IPTable.IpAddress, ClientHost)
//Add Client IP address to IPTable struct
IPTable.IpAddress = append(IPTable.IpAddress, ClientHost)
// Runs speed test to return only servers in the IP table pingable
err = IPTable.SpeedTestUpdatedIPTable()
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
// Runs speed test to return only servers in the IP table pingable
err = IPTable.SpeedTestUpdatedIPTable()
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
// Reads IP addresses from ip table
IpAddresses, err := p2p.ReadIpTable()
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
// Reads IP addresses from ip table
IpAddresses, err := p2p.ReadIpTable()
if err != nil {
c.String(http.StatusOK, fmt.Sprint(err))
}
c.JSON(http.StatusOK, IpAddresses)
})
c.JSON(http.StatusOK, IpAddresses)
})
// Starts docker container in server
r.GET("/startcontainer", func(c *gin.Context) {
// Get Number of ports to open and whether to use GPU or not
Ports := c.DefaultQuery("ports", "0")
GPU := c.DefaultQuery("GPU", "false")
ContainerName := c.DefaultQuery("ContainerName", "")
var PortsInt int
// Starts docker container in server
r.GET("/startcontainer", func(c *gin.Context) {
// Get Number of ports to open and whether to use GPU or not
Ports := c.DefaultQuery("ports", "0")
GPU := c.DefaultQuery("GPU", "false")
ContainerName := c.DefaultQuery("ContainerName", "")
var PortsInt int
// Convert Get Request value to int
fmt.Sscanf(Ports, "%d", &PortsInt)
// Convert Get Request value to int
fmt.Sscanf(Ports, "%d", &PortsInt)
// Creates container and returns-back result to
// access container
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName)
// Creates container and returns-back result to
// access container
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName)
if ProxyIpAddr.Ipv4 != "" {
err := frp.StartFRPCDockerContainer(ProxyIpAddr.Ipv4, ProxyIpAddr.ProxyPort, resp)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
}
if ProxyIpAddr.Ipv4 != "" {
err := frp.StartFRPCDockerContainer(ProxyIpAddr.Ipv4, ProxyIpAddr.ProxyPort, resp)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
}
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
c.JSON(http.StatusOK, resp)
})
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
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")
})
//Show images available
r.GET("/ShowImages", func(c *gin.Context) {
resp, err := docker.ViewAllContainers()
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
c.JSON(http.StatusOK, resp)
})
//Show images available
r.GET("/ShowImages", func(c *gin.Context) {
resp, err := docker.ViewAllContainers()
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
c.JSON(http.StatusOK, resp)
})
//Get Server port based on the config file
config, err := config.ConfigInit()
if err != nil {
return err
}
//Get Server port based on the config file
config, err := config.ConfigInit()
if err != nil {
return err
}
// If there is a proxy port specified
// then starts the FRP server
if config.FRPServerPort != "0" {
go frp.StartFRPProxyFromConfig()
}
// If there is a proxy port specified
// then starts the FRP server
if config.FRPServerPort != "0" {
go frp.StartFRPProxyFromConfig()
}
// 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.IPV6Address == "" || config.FRPServerPort == "0" {
table, err := p2p.ReadIpTable()
if err != nil {
return err
}
// 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 == "True" {
table, err := p2p.ReadIpTable()
if err != nil {
return err
}
var lowestLatency int64
// random large number
lowestLatency = 10000000
var lowestLatencyIpAddress p2p.IpAddress
for i, _ := range table.IpAddress {
// 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 != "" {
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
lowestLatencyIpAddress = table.IpAddress[i]
}
}
var lowestLatency int64
// random large number
lowestLatency = 10000000
var lowestLatencyIpAddress p2p.IpAddress
for i, _ := range table.IpAddress {
// 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 != "" {
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
lowestLatencyIpAddress = table.IpAddress[i]
}
}
// If there is an identified node
if lowestLatency != 10000000 {
// Starts FRP as a client with
proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, lowestLatencyIpAddress.ProxyPort)
if err != nil {
return err
}
// If there is an identified node
if lowestLatency != 10000000 {
// Starts FRP as a client with
proxyPort, err := frp.StartFRPClientForServer(lowestLatencyIpAddress.Ipv4, lowestLatencyIpAddress.ProxyPort, config.ServerPort)
if err != nil {
return err
}
// updating with the current proxy address
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
ProxyIpAddr.ServerPort = proxyPort
ProxyIpAddr.ProxyPort = lowestLatencyIpAddress.ProxyPort
// updating with the current proxy address
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
ProxyIpAddr.ServerPort = proxyPort
ProxyIpAddr.ProxyPort = lowestLatencyIpAddress.ProxyPort
// append the following to the ip table
table.IpAddress = append(table.IpAddress, ProxyIpAddr)
// write information back to the IP Table
table.WriteIpTable()
// update ip table
go table.SpeedTestUpdatedIPTable()
}
// append the following to the ip table
table.IpAddress = append(table.IpAddress, ProxyIpAddr)
// write information back to the IP Table
table.WriteIpTable()
// update ip table
go table.SpeedTest()
}
}
}
// Run gin server on the specified port
err = r.Run(":" + config.ServerPort)
if err != nil {
return err
}
// Run gin server on the specified port
err = r.Run(":" + config.ServerPort)
if err != nil {
return err
}
return nil
return nil
}