package clientIPTable import ( "encoding/json" "fmt" "github.com/Akilan1999/p2p-rendering-computation/config" "github.com/Akilan1999/p2p-rendering-computation/p2p" "io" "io/ioutil" "mime/multipart" "net/http" "os" "sync" ) var mu sync.Mutex // UpdateIpTable Does the following to update it's IP table func UpdateIpTable(IpAddress string, serverPort string, wg *sync.WaitGroup) error { config, err := config.ConfigInit(nil, nil) if err != nil { return err } client := http.Client{} var resp []byte version := p2p.Ip4or6(IpAddress) if version == "version 6" { resp, err = UploadMultipartFile(client, "http://["+IpAddress+"]:"+serverPort+"/IpTable", "json", config.IPTable) if err != nil { return err } } else { resp, err = UploadMultipartFile(client, "http://"+IpAddress+":"+serverPort+"/IpTable", "json", config.IPTable) if err != nil { return err } } if resp == nil { return nil } //resp, err := SendPostRequest("http://"+IpAddress+":8088/IpTable", // config.IPTable, // "json") // //if err != nil { // return err //} var ipStruct p2p.IpAddresses json.Unmarshal(resp, &ipStruct) // Updates IP table based on information provided // by the server if len(ipStruct.IpAddress) > 0 { err = ipStruct.SpeedTestUpdatedIPTable() if err != nil { return err } } err = ipStruct.WriteIpTable() if err != nil { return err } wg.Done() return nil } // UpdateIpTableListClient updates IP tables (Default 3 hops) based on server information available // on the ip tables func UpdateIpTableListClient() error { // Get config information Config, err := config.ConfigInit(nil, nil) if err != nil { return err } // Ensure that the IP Table has Node pingable err = p2p.LocalSpeedTestIpTable() if err != nil { return err } // IP addresses to not append to struct due to // duplication Addresses, err := p2p.ReadIpTable() var DoNotRead p2p.IpAddresses currentIPV4, err := p2p.CurrentPublicIP() if err != nil { return err } var w sync.WaitGroup // Run loop 2 times for i := 0; i < 2; i++ { // Gets information from IP table Addresses, err = p2p.ReadIpTable() if err != nil { return err } //DoNotRead.IpAddress = append(DoNotRead.IpAddress, PublicIP) // Updates IP table based on server IP table for j := range Addresses.IpAddress { Exists := false // If the address is local then add to the local list if currentIPV4 == Addresses.IpAddress[j].Ipv4 && Addresses.IpAddress[j].ServerPort == Config.ServerPort { Exists = true } // Check if IP addresses is there in the struct DoNotRead for k := range DoNotRead.IpAddress { if (DoNotRead.IpAddress[k].Ipv4 == Addresses.IpAddress[j].Ipv4 && DoNotRead.IpAddress[k].ServerPort == Addresses.IpAddress[j].ServerPort) || (DoNotRead.IpAddress[k].Ipv6 != "" && Addresses.IpAddress[j].Ipv6 == DoNotRead.IpAddress[k].Ipv6) { Exists = true break } } // If the struct exists then continues if Exists { continue } w.Add(1) if Addresses.IpAddress[j].Ipv6 != "" { go UpdateIpTable(Addresses.IpAddress[j].Ipv6, Addresses.IpAddress[j].ServerPort, &w) } else if Addresses.IpAddress[j].Ipv4 != currentIPV4 { go UpdateIpTable(Addresses.IpAddress[j].Ipv4, Addresses.IpAddress[j].ServerPort, &w) } w.Wait() //Appends server1 IP address to variable DoNotRead DoNotRead.IpAddress = append(DoNotRead.IpAddress, Addresses.IpAddress[j]) } } return nil } func RemoveOfflineNodes() error { // Ensure that the IP Table has Node pingable err := p2p.LocalSpeedTestIpTable() if err != nil { return err } return nil } // SendPostRequest Sends a file as a //POST request. // Reference (https://stackoverflow.com/questions/51234464/upload-a-file-with-post-request-golang) //func SendPostRequest (url string, filename string, filetype string) ([]byte,error) { // file, err := os.Open(filename) // if err != nil { // return nil,err // } // defer file.Close() // // // body := &bytes.Buffer{} // writer := multipart.NewWriter(body) // part, err := writer.CreateFormFile(filetype, filepath.Base(file.Name())) // // if err != nil { // return nil,err // } // // io.Copy(part, file) // writer.Close() // request, err := http.NewRequest("POST", url, body) // // if err != nil { // return nil,err // } // // request.Header.Add("Content-Type", writer.FormDataContentType()) // client := &http.Client{} // // response, err := client.Do(request) // // if err != nil { // return nil,err // } // defer response.Body.Close() // // content, err := ioutil.ReadAll(response.Body) // // if err != nil { // return nil,err // } // // return content, nil //} func UploadMultipartFile(client http.Client, uri, key, path string) ([]byte, error) { body, writer := io.Pipe() req, err := http.NewRequest(http.MethodPost, uri, body) if err != nil { return nil, err } mwriter := multipart.NewWriter(writer) req.Header.Add("Content-Type", mwriter.FormDataContentType()) errchan := make(chan error) go func() { defer close(errchan) defer writer.Close() defer mwriter.Close() w, err := mwriter.CreateFormFile(key, path) if err != nil { errchan <- err return } in, err := os.Open(path) if err != nil { errchan <- err return } defer in.Close() if written, err := io.Copy(w, in); err != nil { errchan <- fmt.Errorf("error copying %s (%d bytes written): %v", path, written, err) return } if err := mwriter.Close(); err != nil { errchan <- err return } }() resp, err := client.Do(req) if err != nil { return nil, err } content, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } return content, nil }