71 Commits

Author SHA1 Message Date
ce7fa2ccf3 Haskell bindings 2024-09-30 18:22:05 +01:00
4115451875 Haskell bindings 2024-09-30 18:21:50 +01:00
3a40e687a5 work in progress haskell bindings 2024-07-26 21:48:04 +01:00
aa4b18f39d added make clean 2024-03-27 08:28:18 +00:00
f9fb225b91 Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation 2024-03-27 08:06:44 +00:00
7a5cb2f1e3 changes to go.mod 2024-03-27 08:06:23 +00:00
Akilan Selvacoumar
8ff61422d7 Merge pull request #111 from cr2007/docs-markdown-alerts
Adds Alerts Markdown Support
2024-03-14 10:45:30 +00:00
CSK
0c86c6e673 Adds Markdown Alerts for Notes
Reference: https://github.com/orgs/community/discussions/16925

And adds some minor fixes
2024-03-12 14:41:29 +04:00
CSK
00629b604f Adds hyperlink for creating new issue
And some minor fixes in the README.md file
2024-03-12 13:55:37 +04:00
72484da67b Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation 2024-02-23 17:50:11 +00:00
7f1e9cbbae added base abstraction functions and docs to P2PRC 2024-02-23 17:49:55 +00:00
Akilan Selvacoumar
c14a0521c9 Update README.md for extending server. 2024-02-10 22:18:46 +00:00
504cdb41cf added easier use of abstractions 2024-02-10 22:05:47 +00:00
c815ed34d7 fixed mapPort for abstractions 2024-02-10 19:59:46 +00:00
60c4bba380 changing root node 2024-01-10 03:55:11 +00:00
3a2cb47b6e Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation 2023-12-22 00:14:09 +00:00
8c708c6f11 added map port and baremetal mode 2023-12-22 00:13:57 +00:00
83653866e6 added support for baremetal mode 2023-12-20 04:35:04 +00:00
Akilan Selvacoumar
9c94f20ea8 Update README.md 2023-12-16 03:35:20 +00:00
Akilan Selvacoumar
18ae29946d Update README.md 2023-12-16 03:33:17 +00:00
Akilan Selvacoumar
05936a5486 Update README.md 2023-12-16 03:26:56 +00:00
Akilan Selvacoumar
7d5e5cb619 Update README.md 2023-12-16 03:08:03 +00:00
Akilan Selvacoumar
04eea717a6 Update README.md 2023-12-16 03:05:06 +00:00
Akilan Selvacoumar
b6db9147c8 Update README.md 2023-12-16 03:03:49 +00:00
Akilan Selvacoumar
599f7ba2c6 Update README.md 2023-12-16 03:02:03 +00:00
Akilan Selvacoumar
38a05d6ab5 Update README.md 2023-12-16 03:01:10 +00:00
Akilan Selvacoumar
ea08b5c3ea Update Bindings.md 2023-12-16 02:57:44 +00:00
Akilan Selvacoumar
1c496d8be1 Update Bindings.md 2023-12-16 02:55:54 +00:00
Akilan Selvacoumar
a4b9634dc2 Update Bindings.md 2023-12-16 02:39:22 +00:00
Akilan Selvacoumar
65b90d7ce9 Update Bindings.md 2023-12-16 02:17:25 +00:00
Akilan Selvacoumar
95ab45bf62 Update Bindings.md 2023-12-16 02:08:26 +00:00
751f1b15a6 added binding docs 2023-12-15 18:33:28 +00:00
8ccdcaefb5 Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation 2023-12-15 17:16:10 +00:00
213838715b fixed adding public key as parameter when spawning a container 2023-12-15 17:15:57 +00:00
Akilan Selvacoumar
f899b4e6bb Update README.md 2023-12-15 03:45:00 +00:00
2704caa5e4 added public-private keys for all docker containers 2023-12-15 03:42:06 +00:00
2b6c7a5963 added support to generate Public and Private keys 2023-12-15 02:08:11 +00:00
b78c009f9f modifed shared object calls for python bindings 2023-11-16 15:17:05 +00:00
708eacd1db added support for python bindings 2023-11-10 21:00:24 +00:00
979e856272 pushed changes relating P2PRC changes for python bindings 2023-11-10 18:17:28 +00:00
614a3412c5 pushed changes relating P2PRC changes for python bindings 2023-11-10 18:17:15 +00:00
ea90348fd2 added shared starter tests and added to Makefile to add compile .h and .so files 2023-10-05 17:07:21 +01:00
Akilan Selvacoumar
a07c91c888 Merge pull request #107 from xecarlox94/master
modifying nix config
2023-09-27 17:40:48 +01:00
636646b0a1 modifying nix files, adding adding building, and docker (VIM as well) 2023-09-27 17:38:50 +01:00
3933b29979 merged pull request 2023-09-27 17:28:28 +01:00
96e755bc19 added flag to add custom metadata 2023-09-27 17:27:52 +01:00
Akilan Selvacoumar
7f0a43625b Merge pull request #106 from xecarlox94/master
adding nix shell development environment
2023-09-27 16:29:16 +01:00
29eff7a3af adding nix shell development environment, tested 2023-09-27 16:27:17 +01:00
7ed25ef4b3 added JSON response for IPTables 2023-09-27 15:27:25 +01:00
6b287f2cf1 added docker templating and introducted possbility to change the baseimage name 2023-08-23 22:45:46 +01:00
dfa8713aea fixed tracked container issue 2023-07-29 15:42:05 +01:00
263275d80c remove nodes not pingable 2023-07-15 00:07:14 +01:00
9caf6cde07 saving current changes 2023-07-14 17:54:56 +01:00
d71bd991b0 modified README files and changed version to v2.0.0 2023-07-14 16:51:48 +01:00
e21465b1eb modified README files and changed version to v2.0.0 2023-07-14 16:49:43 +01:00
fb606cf4ff merged from master 2023-07-14 16:31:17 +01:00
136243d6a5 added new IPTable entries 2023-07-14 16:30:20 +01:00
Akilan Selvacoumar
2f6116993b Merge pull request #101 from cr2007/master
Updates the `CITATION.cff` file
2023-07-11 10:27:35 +01:00
Chandrashekhar R
0665a82815 Merge branch 'Akilan1999:master' into master 2023-07-07 09:31:33 +04:00
Chandrashekhar R
a7d741909c Updates the version, release date in CITATION.cff 2023-07-07 09:31:25 +04:00
Akilan Selvacoumar
232c13aca0 Merge pull request #100 from cr2007/master
Polishes up the Documentation
2023-07-06 15:39:38 +01:00
Chandrashekhar R
70aa82a946 Adds buttons to go to the previous/next section of documentation 2023-07-06 14:24:42 +04:00
Akilan Selvacoumar
8f4c2623e3 Update ConfigImplementation.md 2023-06-08 16:50:50 +01:00
Akilan Selvacoumar
a038bf9f20 Update CliImplementation.md 2023-06-08 16:49:27 +01:00
Akilan Selvacoumar
683e20953b Update ServerImplementation.md 2023-06-08 16:43:59 +01:00
Akilan Selvacoumar
8e6a6e246c Update P2PImplementation.md 2023-06-08 16:41:42 +01:00
Akilan Selvacoumar
06e5e1e67f Update ClientImplementation.md 2023-06-08 16:07:38 +01:00
Akilan Selvacoumar
2b191af951 Update ClientImplementation.md 2023-06-08 16:06:38 +01:00
Akilan Selvacoumar
85ac36d51b Update Client.md 2023-06-08 16:04:28 +01:00
Akilan Selvacoumar
64225b85b7 Update Client.md 2023-06-08 16:02:28 +01:00
Akilan Selvacoumar
66b26c5ea2 Update Introduction.md 2023-06-08 16:01:29 +01:00
52 changed files with 2518 additions and 1376 deletions

BIN
.DS_Store vendored

Binary file not shown.

14
.gitignore vendored
View File

@@ -21,6 +21,20 @@ generate/Test
#ignore windows exe files #ignore windows exe files
*.exe *.exe
dist/ dist/
# Ignore any sort of logs
logs/
# ignore docker image files # ignore docker image files
server/docker/containers/ server/docker/containers/
*.h
*.so
# generic folder to ignore
export/
# Any testing file
test*
# Ignore public and private keys
p2prc.publicKey
p2prc.privateKey

170
Bindings/Client.go Normal file
View File

@@ -0,0 +1,170 @@
package main
import "C"
import (
"encoding/json"
"fmt"
"time"
"github.com/Akilan1999/p2p-rendering-computation/abstractions"
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
)
// The Client package where data-types
// are manually converted to the
// to a string so that it can
// be export
// --------------------------------- Container Control ----------------------------------------
//export StartContainer
func StartContainer(IP *C.char) (output *C.char) {
container, err := abstractions.StartContainer(C.GoString(IP))
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(container)
}
//export RemoveContainer
func RemoveContainer(IP *C.char, ID *C.char) (output *C.char) {
err := abstractions.RemoveContainer(C.GoString(IP), C.GoString(ID))
if err != nil {
return C.CString(err.Error())
}
return C.CString("Success")
}
// --------------------------------- Plugin Control ----------------------------------------
// DEPRECATED
////export ViewPlugin
//func ViewPlugin() (output *C.char) {
// plugins, err := plugin.DetectPlugins()
// if err != nil {
// return C.CString(err.Error())
// }
// return ConvertStructToJSONString(plugins)
//}
//
////export PullPlugin
//func PullPlugin(pluginUrl string) (output *C.char) {
// err := plugin.DownloadPlugin(pluginUrl)
// if err != nil {
// return C.CString(err.Error())
// }
// return C.CString("Success")
//}
//
////export DeletePlugin
//func DeletePlugin(pluginName string) (output *C.char) {
// err := plugin.DeletePlugin(pluginName)
// if err != nil {
// return C.CString(err.Error())
// }
// return C.CString("Success")
//}
//
////export ExecutePlugin
//func ExecutePlugin(pluginname string, ContainerID string) (output *C.char) {
// err := plugin.RunPluginContainer(pluginname, ContainerID)
// if err != nil {
// return C.CString(err.Error())
// }
// return C.CString("Success")
//}
// --------------------------------- Get Specs ----------------------------------------
//export GetSpecs
func GetSpecs(IP *C.char) (output *C.char) {
specs, err := abstractions.GetSpecs(C.GoString(IP))
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(specs)
}
//export Init
func Init(customConfig *C.char) (output *C.char) {
init, err := abstractions.Init(C.GoString(customConfig))
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(init)
}
// --------------------------------- P2P Controls -----------------------------------
//export ViewIPTable
func ViewIPTable() (output *C.char) {
table, err := abstractions.ViewIPTable()
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(table)
}
//export UpdateIPTable
func UpdateIPTable() (output *C.char) {
err := abstractions.UpdateIPTable()
if err != nil {
return C.CString(err.Error())
}
return C.CString("Success")
}
//export EscapeFirewall
func EscapeFirewall(HostOutsideNATIP *C.char, HostOutsideNATPort *C.char, internalPort *C.char) (output *C.char) {
// Get free port from P2PRC server node
serverPort, err := frp.GetFRPServerPort("http://" + C.GoString(HostOutsideNATIP) + ":" + C.GoString(HostOutsideNATPort))
if err != nil {
return C.CString(err.Error())
}
time.Sleep(5 * time.Second)
ExposedPort, err := frp.StartFRPClientForServer(C.GoString(HostOutsideNATIP)+":"+C.GoString(HostOutsideNATPort), serverPort, C.GoString(internalPort), "")
if err != nil {
return C.CString(err.Error())
}
return C.CString(ExposedPort)
}
//export MapPort
func MapPort(Port *C.char) *C.char {
fmt.Println(C.GoString(Port))
entireAddress, _, err := abstractions.MapPort(C.GoString(Port))
if err != nil {
return C.CString(err.Error())
}
return C.CString(entireAddress)
}
// --------------------------------- Controlling Server ----------------------------------------
//export Server
func Server() (output *C.char) {
_, err := abstractions.Start()
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString("")
}
// --------------------------------- Helper Functions ----------------------------------------
func ConvertStructToJSONString(Struct interface{}) *C.char {
jsonBytes, err := json.Marshal(Struct)
if err != nil {
return C.CString(err.Error())
}
// Convert the JSON bytes to a string
return C.CString(string(jsonBytes))
}
func main() {}

BIN
Bindings/python/.DS_Store vendored Normal file

Binary file not shown.

11
Bindings/python/p2prc.py Normal file
View File

@@ -0,0 +1,11 @@
import ctypes
p2prc = ctypes.CDLL("SharedOBjects/p2prc.so")
p2prc.Init("")
def StartServer():
# Starting P2PRC as a server mode
p2prc.Server()
for _ in iter(int, 1):
pass

View File

@@ -5,5 +5,5 @@ authors:
given-names: Akilan given-names: Akilan
title: P2PRC title: P2PRC
license: "GPL-2.0" license: "GPL-2.0"
version: 1.0.0 version: 2.0.0
date-released: 2021-07-22 date-released: 2023-06-08

BIN
Docs/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -1,6 +1,20 @@
# Abstractions # Abstractions
| [◀ Previous](Installation.md) | [Next ▶](Implementation.md) |
|:-----------:|---------|
The Abstractions package consists of black-boxed functions for P2PRC. The Abstractions package consists of black-boxed functions for P2PRC.
## Functions ## Functions
- ```Init(<Project name>)```: Initializes P2PRC with all the needed configurations. - ```Init(<Project name>)```: Initializes P2PRC with all the needed configurations.
- ```Start()```: Starts p2prc as a server and makes it possible to extend by adding other routes and functionality to P2PRC. - ```Start()```: Starts p2prc as a server and makes it possible to extend by adding other routes and functionality to P2PRC.
- ```MapPort(<port no>)```: On the local machine the port you want to export to world.
- ```StartContainer(<ip address>)```: The machine on the p2p network where you want to spin up a docker container.
- ```RemoveContainer(<ip address>,<container id>)```: Terminate container based on the IP address and container name.
- ```GetSpecs(<ip address>)```: Get specs of a machine on the network based on the IP address.
- ```ViewIPTable()```: View the IP table which about nodes in the network.
- ```UpdateIPTable()```: Force update IP table to learn about new nodes faster.
---
### Next Chapter: [Implementation](Implementation.md)

139
Docs/Bindings.md Normal file
View File

@@ -0,0 +1,139 @@
# Language Bindings
[Language bindings](https://en.wikipedia.org/wiki/Language_binding) refers to wrappers to bridge 2 programming languages. This is used in P2PRC to extend calling P2PRC functions in other programming languages. Currently this is done by generating ```.so``` and ```.h``` from the Go compiler.
<br>
## How to build shared object files
#### The easier way
```bash
# Run
make sharedObjects
```
#### Or the direct way
```bash
# Run
cd Bindings && go build -buildmode=c-shared -o p2prc.so
```
#### If successfully built:
```bash
# Enter into the Bindings directory
cd Bindings
# List files
ls
# Find files
p2prc.h p2prc.so
```
<br>
## Workings under the hood
Below are a sample set of commands to
open the bindings implementation.
```
# run
cd Bindings/
# list files
ls
# search for file
Client.go
```
### In Client go
There a few things to notice which are different from
your standard Go programs:
#### 1. We import "C" which means [Cgo](https://pkg.go.dev/cmd/cgo) is required.
```go
import "C"
```
#### 2. All functions which are required to be called from other programming languages have comment such as.
```go
//export <function name>
// ------------ Example ----------------
// The function below allows to externally
// to call the P2PRC function to start containers
// in a specific node in the know list of nodes
// in the p2p network.
// Note: the comment "//export StartContainer".
//export StartContainer
func StartContainer(IP string) (output *C.char) {
container, err := client.StartContainer(IP, 0, false, "", "")
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(container)
}
```
#### 3. While looking through the file (If 2 files are compared it is pretty trivial to notice a common structure).
```go
// --------- Example ------------
//export StartContainer
func StartContainer(IP string) (output *C.char) {
container, err := client.StartContainer(IP, 0, false, "", "")
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(container)
}
//export ViewPlugin
func ViewPlugin() (output *C.char) {
plugins, err := plugin.DetectPlugins()
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(plugins)
}
```
#### It is easy to notice that:
- ```ConvertStructToJSONString(<go object>)```: This is a helper function that convert
a go object to JSON string initially and converts it to ```CString```.
- ```(output *C.char)```: This is the return type for most of the functions.
#### A Pseudo code to refer to the common function implementation shape could be represented as:
```
func <Function name> (output *C.char) {
<response>,<error> := <P2PRC function name>(<parameters if needed>)
if <error> != nil {
return C.CString(<error>.Error())
}
return ConvertStructToJSONString(<response>)
}
```
<br>
## Current languages supported
- Python
### Build sample python program
The easier way
```bash
# Run
make python
# Expected ouput
Output is in the Directory Bindings/python/export/
# Run
cd Bindings/python/export/
# list files
ls
# Expected output
SharedObjects/ p2prc.py
```
Above shows a generated folder which consists of a folder
called "SharedObjects/" which consists of ```p2prc.so```
and ```p2prc.h``` files. ```p2prc.py``` refers to a
sample python script calling P2PRC go functions.
To start an any project to extend P2PRC with python,
This generated folder can copied and created as a new
git repo for P2PRC extensions scripted or used a reference
point as proof of concept that P2PRC can be called from
other programming languages.

View File

@@ -6,7 +6,7 @@ commands as possible. The cli was built using the library called urfave cli v2 .
major files created named as flags.go and actions.go. major files created named as flags.go and actions.go.
### Flags.go ### Flags.go
The flags .go file is responsible to create the appropriate flags for the cli. There are 2 types of flags The flags .go file is responsible to create the appropriate flags for the cli. There are 2 types of flags
called boolean and string as described in Fig 5.3.1. Each of the flags outputs are assigned to a called boolean and string. Each of the flags outputs are assigned to a
variable to be handled. The flags can also detect environment variables set. This feature is useful variable to be handled. The flags can also detect environment variables set. This feature is useful
because if the user wants to call certain flags in a repeated sequence it only has to be initialized because if the user wants to call certain flags in a repeated sequence it only has to be initialized
once. once.

View File

@@ -1,25 +1,13 @@
# Client Module # Client Module
This module is incharge of communicating with the server and receiving the appropriate information back from the server. This module is incharge of communicating with the server and receiving the appropriate information back from the server.
Note: To [read more about the functions](https://pkg.go.dev/git.sr.ht/~akilan1999/p2p-rendering-computation@v0.0.0-20210404191839-6a046babcb02/client)
## Functions of the Client Module ## Functions of the Client Module
- [Interact with the Server Api](#functions-of-the-client-module) <!-- - [Interact with the Server Api](#functions-of-the-client-module) -->
- [Decision maker on how the ip table is created or updated](#decision-maker-on-how-the-ip-table-is-created-or-updated) - [Decision maker on how the ip table is created or updated](#decision-maker-on-how-the-ip-table-is-created-or-updated)
## Interact with the Server Api
This sections talks about the functionality implemented till now.
- The client can start docker containers using the function StartContainer.
This functions calls the route:
```
http://<server IP address>:<server port>/startcontainer
```
TODO: Outputs and how it's printed
## Decision maker on how the IP table is created or updated ## Decision maker on how the IP table is created or updated
- Does a local speedtest to verify and see if the server IP's in the IP table - Does a local speedtest to verify and see if the server IP's in the IP table
are pingable. are pingable.
- Downloads the Servers IP table.
- Tries to ping the servers IP Table addresses. - Tries to ping the servers IP Table addresses.
- If it's pingable then it's added as a new entry in the IP table. - If it's pingable then it's added as a new entry in the IP table.
- The following steps occurs in the clients IP table. - The following steps occurs in the clients IP table.

View File

@@ -1,5 +1,10 @@
# Client Module Implementation # Client Module Implementation
The Client Module interacts with the P2P module and Server Module. It is responsible for interacting with the server module and appropriately updating the IP table on the client side. It connects to the server using the server's REST Apis. It is also the primary decision maker on how the IP table is updated is on the client side. This is because each user can have requirements like how many number of hops they would want to do to update their IP table. Hops is the number of times the client is going to download the IP table from different servers ,once it gets the IP tables from the previous servers.
![Visual demonstration of hops](images/NumOfHops.png)
![UML diagram of client module](images/clientmoduleArch.png)
## Topics ## Topics
1. [Updating the IP table](#updating-the-IP-table) 1. [Updating the IP table](#updating-the-IP-table)
2. [Reading server specifications](#reading-server-specifications) 2. [Reading server specifications](#reading-server-specifications)
@@ -78,8 +83,6 @@ show a sample structure of file ```grouptrackcontainer.json```.
``` ```
The default path to the container tracker is ```client/trackcontainers/grouptrackcontainer.json```. The default path to the container tracker is ```client/trackcontainers/grouptrackcontainer.json```.
### Note: > [!NOTE]
The group id will be auto-generated and will have its own prefix in the start which will mostly be ```grp<UUID>```. > The group id will be auto-generated and will have its own prefix in the start which will mostly be ```grp<UUID>```.
When a container is removed using the command. ```p2prc --rm <IP Address> --id <Container id>```. It will be automatically deleted > When a container is removed using the command. ```p2prc --rm <IP Address> --id <Container id>```. It will be automatically deleted from the groups it exists in.
from the groups it exists in.

View File

@@ -13,9 +13,19 @@ JSON format.
```json ```json
{ {
"dockerfile": "/<path>/p2p-rendering-computation/server/docker/containers/docker-ubuntu-sshd/", "MachineName": "pc-74-120.customer.ask4.lan",
"iptable": "/<path>/p2p-rendering-computation/p2p/ip_table.json", "IPTable": "/Users/akilan/Documents/p2p-rendering-computation/p2p/iptable/ip_table.json",
"speedtestfile": "/<path>/p2p-rendering-computation/p2p/50.bin" "DockerContainers": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/",
"DefaultDockerFile": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/docker-ubuntu-sshd/",
"SpeedTestFile": "/Users/akilan/Documents/p2p-rendering-computation/p2p/50.bin",
"IPV6Address": "",
"PluginPath": "/Users/akilan/Documents/p2p-rendering-computation/plugin/deploy",
"TrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/trackcontainers.json",
"ServerPort": "8088",
"GroupTrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/grouptrackcontainers.json",
"FRPServerPort": "True",
"BehindNAT": "True",
"CustomConfig": null
} }
``` ```

View File

@@ -1,20 +1,23 @@
# Implementation # Implementation
| [◀ Previous](Introduction.md) | [Back to TOC](README.md) |
|:-----------:|---------|
This chapter describes how the project was built. It talks in depth of the implementation This chapter describes how the project was built. It talks in depth of the implementation
performed to give a better understanding of the project. performed to give a better understanding of the project.
## Programming langauge used ## Programming langauge used
The programming language used for this project was Golang. The reason Go lang was chosen was The programming language used for this project was [Golang](https://go.dev/). The reason Go lang was chosen was
because it is a compiled language. because it is a compiled language.<br>
The entire codebase is just a single binary file. When The entire codebase is just a single binary file. When
distributing to other linux distributing the only requirement would be the binary file to run the distributing to other linux distributing the only requirement would be the binary file to run the
code. It is easy to write independant modules and be monolithic at the sametime using Go. Using code. It is easy to write independant modules and be monolithic at the sametime using Go.<br>
Go.mod makes it very easy to handle external libraries and modularise code. The go.mod name for Using Go.mod makes it very easy to handle external libraries and modularise code. The go.mod name for
the project is git.sr.ht/~akilan1999/p2p-rendering-computation. the project is [git.sr.ht/~akilan1999/p2p-rendering-computation](https://git.sr.ht/~akilan1999/p2p-rendering-computation).
## [Cli Module](CliImplementation.md) - ## [Cli Module](CliImplementation.md)
## [Config Module](ConfigImplementation.md) - ## [Config Module](ConfigImplementation.md)
## [Server Module](ServerImplementation.md) - ## [Server Module](ServerImplementation.md)
## [Client Module](ClientImplementation.md) - ## [Client Module](ClientImplementation.md)
## [P2P Module](P2PImplementation.md) - ## [P2P Module](P2PImplementation.md)
## [Plugin Module](PluginImplementation.md) - ## [Plugin Module](PluginImplementation.md)
## [Generate Module](GenerateImplementation.md) - ## [Generate Module](GenerateImplementation.md)

View File

@@ -1,5 +1,8 @@
# Installation # Installation
| [◀ Previous](Introduction.md) | [Next ▶](Abstractions.md) |
|:-----------:|---------|
Over here we will cover the basic steps to get the server and client side running. Over here we will cover the basic steps to get the server and client side running.
## Latest release install ## Latest release install
@@ -39,7 +42,7 @@ To set up P2PRC on Windows, simply run this batch file.
.\install.bat .\install.bat
``` ```
### Add appropriate paths to .bashrc ### Add appropriate paths to `.bashrc`
``` ```
export P2PRC=/<PATH>/p2p-rendering-computation export P2PRC=/<PATH>/p2p-rendering-computation
export PATH=/<PATH>/p2p-rendering-computation:${PATH} export PATH=/<PATH>/p2p-rendering-computation:${PATH}
@@ -65,7 +68,7 @@ USAGE:
p2prc [global options] command [command options] [arguments...] p2prc [global options] command [command options] [arguments...]
VERSION: VERSION:
<version no> 2.0.0
COMMANDS: COMMANDS:
help, h Shows a list of commands or help for one command help, h Shows a list of commands or help for one command
@@ -78,6 +81,7 @@ GLOBAL OPTIONS:
--ViewImages value, --vi value View images available on the server IP address [$VIEW_IMAGES] --ViewImages value, --vi value View images available on the server IP address [$VIEW_IMAGES]
--CreateVM value, --touch value Creates Docker container on the selected server [$CREATE_VM] --CreateVM value, --touch value Creates Docker container on the selected server [$CREATE_VM]
--ContainerName value, --cn value Specifying the container run on the server side [$CONTAINER_NAME] --ContainerName value, --cn value Specifying the container run on the server side [$CONTAINER_NAME]
--BaseImage value, --bi value Specifying the docker base image to template the dockerfile [$CONTAINER_NAME]
--RemoveVM value, --rm value Stop and Remove Docker container (IP:port) accompanied by container ID via --ID or --id [$REMOVE_VM] --RemoveVM value, --rm value Stop and Remove Docker container (IP:port) accompanied by container ID via --ID or --id [$REMOVE_VM]
--ID value, --id value Docker Container ID [$ID] --ID value, --id value Docker Container ID [$ID]
--Ports value, -p value Number of ports to open for the Docker Container [$NUM_PORTS] --Ports value, -p value Number of ports to open for the Docker Container [$NUM_PORTS]
@@ -93,10 +97,13 @@ GLOBAL OPTIONS:
--Groups, --groups View all groups (default: false) [$GROUPS] --Groups, --groups View all groups (default: false) [$GROUPS]
--RemoveContainerGroup, --rmcgroup Remove specific container in the group (default: false) [$REMOVE_CONTAINER_GROUP] --RemoveContainerGroup, --rmcgroup Remove specific container in the group (default: false) [$REMOVE_CONTAINER_GROUP]
--RemoveGroup value, --rmgroup value Removes the entire group [$REMOVE_GROUP] --RemoveGroup value, --rmgroup value Removes the entire group [$REMOVE_GROUP]
--MAPPort value, --mp value Maps port for a specific port provided as the parameter [$MAPPORT]
--DomainName value, --dn value While mapping ports allows to set a domain name to create a mapping in the proxy server [$DOMAINNAME]
--Generate value, --gen value Generates a new copy of P2PRC which can be modified based on your needs [$GENERATE] --Generate value, --gen value Generates a new copy of P2PRC which can be modified based on your needs [$GENERATE]
--ModuleName value, --mod value New go project module name [$MODULENAME] --ModuleName value, --mod value New go project module name [$MODULENAME]
--PullPlugin value, --pp value Pulls plugin from git repos [$PULLPLUGIN] --PullPlugin value, --pp value Pulls plugin from git repos [$PULLPLUGIN]
--RemovePlugin value, --rp value Removes plugin [$REMOVEPLUGIN] --RemovePlugin value, --rp value Removes plugin [$REMOVEPLUGIN]
--AddMetaData value, --amd value Adds metadata about the current node in the p2p network which is then propagated through the network [$ADDMETADATA]
--help, -h show help (default: false) --help, -h show help (default: false)
--version, -v print the version (default: false) --version, -v print the version (default: false)
@@ -111,7 +118,7 @@ GLOBAL OPTIONS:
# Using basic commands # Using basic commands
### Start as a server ### Start as a server
Do ensure you have docker installed for this Do ensure you have Docker installed for this
``` ```
p2prc -s p2prc -s
``` ```
@@ -205,6 +212,16 @@ p2prc --pp <repo link>
p2prc --rp <plugin name> p2prc --rp <plugin name>
``` ```
### Added custom metadata about the current node
```
p2prc --amd "custom metadata"
```
### Map port
```
p2prc --mp <internal port no from your machine> --dn <domain name you want the port linked to>
```
<br> <br>
-------------- --------------
@@ -223,14 +240,14 @@ This feature is still Under Development:
#### Run Test Cases #### Run Test Cases
- Generate Test Case Ansible file - Generate Test Case Ansible file
- ```make testcases``` - ```make testcases```
- Enter inside plugin directory and run tests. - Enter inside plugin directory and run tests.<br>
Note: That docker needs to installed and needs to run without
sudo. Refer the section install Docker.
- ```cd plugin```
- ```go test .```
> [!NOTE]
> That docker needs to installed and needs to run without
> sudo. Refer the section [Install Docker](#install-docker).
> - ```cd plugin```
> - ```go test .```
---
### Next Chapter: [Abstractions](Abstractions.md)

View File

@@ -1,5 +1,8 @@
# Chapter 1: Introduction # Chapter 1: Introduction
| [◀ Back to TOC](README.md) | [Next ▶](Installation.md) |
|:-----------:|---------|
## Abstract ## Abstract
This project focuses on creating a framework on running heavy tasks that a regular computer This project focuses on creating a framework on running heavy tasks that a regular computer
cannot run easily such as graphically demanding video games, rendering 3D animations , protein cannot run easily such as graphically demanding video games, rendering 3D animations , protein
@@ -21,7 +24,7 @@ run these heavy tasks can be really useful. Ethically speaking this is leading t
computing power similar to what is happening in the web server area. By using peer to peer computing power similar to what is happening in the web server area. By using peer to peer
principles it is possible to remove the monopolisation factor and increase the bandwidth between principles it is possible to remove the monopolisation factor and increase the bandwidth between
the client and server. the client and server.
<!--
## Aim ## Aim
This project aims to create a peer to peer (p2p) network, where a user can use the p2p network to This project aims to create a peer to peer (p2p) network, where a user can use the p2p network to
act as a client (i.e sending tasks) or the server (i.e executing the tasks). A prototype application will act as a client (i.e sending tasks) or the server (i.e executing the tasks). A prototype application will
@@ -33,4 +36,8 @@ or virtual environments across selected nodes.
rendering tools and tools to batch any sort of tasks. rendering tools and tools to batch any sort of tasks.
- Creating p2p network - Creating p2p network
- Server to create a containerised environment - Server to create a containerised environment
- The client node to run tasks on Server containerised node - The client node to run tasks on Server containerised node -->
---
### Next Chapter: [Installation](Installation.md)

View File

@@ -23,5 +23,5 @@ In this repository the P2P module has been designed from sratch at the point of
- Taking to nodes behind NAT. [More about the implementation](NAT-Traversal)... - Taking to nodes behind NAT. [More about the implementation](NAT-Traversal)...
## Note: > [!NOTE]
If you are running in server mode it is recommended to use [DMZ](https://routerguide.net/when-and-how-to-setup-dmz-host-for-home-use/) to bypass the [NAT](https://en.wikipedia.org/wiki/Network_address_translation). > If you are running in server mode it is recommended to use [DMZ](https://routerguide.net/when-and-how-to-setup-dmz-host-for-home-use/) to bypass the [NAT](https://en.wikipedia.org/wiki/Network_address_translation).

View File

@@ -1,10 +1,20 @@
# P2P Module Implementation # P2P Module Implementation
The P2P module (i.e Peer to Peer Module) is responsible for storing the IP table and interacting
with the IP table. In the following implementation of the P2P module ,the IP table stores
information about servers available in the network. The other functionality the P2P module takes
care of is doing the appropriate speed tests to the servers in the IP table. This is for informing the
users about nodes which are close by and nodes which have quicker uploads and downloads
speeds. The module is responsible to ensure that there are no duplicate server IPs in the IP table
and to remove all server IPs which are not pingable.
![UML diagram of P2P module](images/p2pmoduleArch.png)
The peer to peer implementation was built from scratch. This is because other peer to peer The peer to peer implementation was built from scratch. This is because other peer to peer
libraries were on the implementation of the Distributed hash table. At the current moment all libraries were on the implementation of the Distributed hash table. At the current moment all
those heavy features are not needed because the objective is to search and list all possible servers those heavy features are not needed because the objective is to search and list all possible servers
available. The limitation being that to be a part of the network the user has to know at least 1 available. The limitation being that to be a part of the network the user has to know at least 1
server and has to have DMZ enabled from the router if the user wants to act as a server out of the server. The advantage of building from scratch makes the module super light and
users local network. The advantage of building from scratch makes the module super light and
possibility for custom functions and structs. The sub topics below will mention the possibility for custom functions and structs. The sub topics below will mention the
implementations of each functionality in depth. implementations of each functionality in depth.
@@ -32,3 +42,44 @@ path of the IP table json file is received from the configuration module.
### Latency ### Latency
The latency is measured in milliseconds. The route /server_info is called from the The latency is measured in milliseconds. The route /server_info is called from the
server and time it takes to provide a json response is recorded. server and time it takes to provide a json response is recorded.
## NAT Traversal
P2PRC currently supports TURN for NAT traversal.
## TURN
The current TURN implementation used is FRP. The TURN server is also required when
a P2PRC node is acting as a Server. The TURN server is determined based on the Node
with the least amount of latency based on the Nodes available on the IPTable.
Once a TURN server is determined there are 2 actions performed. The first one is
```/FRPPort``` to the TURN server to receive a port which is used to generate the external
port from the TURN server. The flow below describes the workflow.
### Client mode
- Call ```/FRPPort```
```
http://<turn server ip>:<server port no>/FRPport
```
- Call the TURN server in the following manner. The following is a sample code snippet below.
```go
import (
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
)
func main() {
serverPort, err := frp.GetFRPServerPort("http://" + <lowestLatencyIpAddress.Ipv4> + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil {
return nil, err
}
// Create 1 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, <the port you want to expose externally>)
if err != nil {
return nil, err
}
}
```

View File

@@ -54,22 +54,23 @@ nodes to execute Ansible instructions. In this project this file needs to be set
go code or binary will populate this file automatically with the appropriate information required to connect to local or go code or binary will populate this file automatically with the appropriate information required to connect to local or
remote containers. remote containers.
#### Note: Add as exactly specified below > [!NOTE]
``` > Add as exactly specified below:
all: > ```
vars: >all:
ansible_python_interpreter: /usr/bin/python3 // Path to your python 3 interpreter > vars:
main: > ansible_python_interpreter: /usr/bin/python3 // Path to your python 3 interpreter
hosts: >main:
host1: > hosts:
// Note: These values will be automatically overwritten > host1:
// by the Go functions > // Note: These values will be automatically overwritten
ansible_host: 0.0.0.0 > // by the Go functions
ansible_port: 39269 > ansible_host: 0.0.0.0
ansible_user: master > ansible_port: 39269
ansible_ssh_pass: password > ansible_user: master
ansible_sudo_pass: password > ansible_ssh_pass: password
``` > ansible_sudo_pass: password
>```
## Ports.json ## Ports.json
The ```ports.json``` file is intended to mention the number of ports required The ```ports.json``` file is intended to mention the number of ports required

View File

@@ -14,5 +14,6 @@
4. [Config Module](ConfigImplementation.md) 4. [Config Module](ConfigImplementation.md)
5. [Cli Module](CliImplementation.md) 5. [Cli Module](CliImplementation.md)
6. [Plugin Module](PluginImplementation.md) 6. [Plugin Module](PluginImplementation.md)
7. [Language bindings](Bindings.md)
<!-- 5. [Problems](https://github.com/Akilan1999/p2p-rendering-computation/issues) --> <!-- 5. [Problems](https://github.com/Akilan1999/p2p-rendering-computation/issues) -->

View File

@@ -4,6 +4,14 @@ This section focuses on an in-depth understanding of the server module implement
understand the architecture of the server module refer. The server module can be split understand the architecture of the server module refer. The server module can be split
into various sections. Each section will provide information on how a certain feature works. into various sections. Each section will provide information on how a certain feature works.
The server module takes care of setting and removing the virtualization environment (i.e
containers) for accessing and doing the appropriate computation. It also interacts with the peer to
peer module to update the IP table on the server side. The server module
accesses information regarding CPU and GPU specifications of the machine running the server
module. To do Speed tests the server has routes which allows it to upload and download a 50mb.
![UML diagram of server module](images/servermoduleArch.png)
## Web framework ## Web framework
The web framework used for the server module is called Gin. The reason Gin was chosen is due to The web framework used for the server module is called Gin. The reason Gin was chosen is due to
its wide use and strong documentation available on the official github repository. The default its wide use and strong documentation available on the official github repository. The default

View File

@@ -9,3 +9,12 @@ testcases:
run: run:
go run main.go go run main.go
sharedObjects:
sh build-bindings.sh
python:
sh build-python-package.sh
clean:
go clean -modcache
rm -fr .go-build vendor result*

View File

@@ -1,3 +1,6 @@
> [!NOTE]
> Fixing documentation to latest changes. If you have any questions setting up P2PRC either [create an issue](https://github.com/Akilan1999/p2p-rendering-computation/issues/new/choose) or send me an email (me AT akilan dot io).
> Currently HEAD is always intended to stay on a working state. It is recommended to always use HEAD in your go.mod file.
<h1 align="center"> <h1 align="center">
<br> <br>
@@ -18,20 +21,40 @@ The main aim of this project was to create a custom peer to peer network. The us
client has total flexibility on how to batch the tasks and the user acting as the server has complete client has total flexibility on how to batch the tasks and the user acting as the server has complete
flexibility on tracking the container's usages and killing the containers at any point of time. flexibility on tracking the container's usages and killing the containers at any point of time.
## Gophers talk ## Latest tutorial
[![IMAGE ALT TEXT](https://i.ytimg.com/vi/ovcZLEhQxWk/hqdefault.jpg)](https://www.youtube.com/watch?v=ovcZLEhQxWk "P2PRC - Gophers monthly talk") [![IMAGE ALT TEXT](https://i.ytimg.com/vi/OMwCpedu5cs/hqdefault.jpg)](https://www.youtube.com/watch?v=OMwCpedu5cs")
<br> <br>
## Table of contents ## Table of contents in the current README
1. [Introduction](#Introduction) 1. [Introduction](#Introduction)
2. [Installation](#Installation.md) 2. [Installation](#extend-your-application-with-p2prc)
3. [Design Architecture](#Design-Architecture) 3. [Design Architecture](#Design-Architecture)
4. [Implementation](#Implementation) 4. [Implementation](#Implementation)
5. [Find out more](#Find-out-more) 5. [Find out more](#Find-out-more)
<br> <br>
# Table of contents in the Docs folder
1. [Introduction](Docs/Introduction.md)
2. [Installation](Docs/Installation.md)
3. [Abstractions](Docs/Abstractions.md)
<!-- 3. [Design Architecture](DesignArchtectureIntro.md)
1. [Client Module](ClientArchitecture.md)
2. [P2P Module](P2PArchitecture.md)
3. [Server Module](ServerArchitecture.md) -->
4. [Implementation](Docs/Implementation.md)
1. [Client Module](Docs/ClientImplementation.md)
2. [P2P Module](Docs/P2PImplementation.md)
3. [Server Module](Docs/ServerImplementation.md)
4. [Config Module](Docs/ConfigImplementation.md)
5. [Cli Module](Docs/CliImplementation.md)
6. [Plugin Module](Docs/PluginImplementation.md)
7. [Language Bindings](Docs/Bindings.md)
<!-- 5. [Problems](https://github.com/Akilan1999/p2p-rendering-computation/issues) -->
<br>
## Introduction ## Introduction
This project aims to create a peer to peer (p2p) network, where a user can use the p2p network to act as a client (i.e sending tasks) or the server (i.e executing the tasks). A prototype application will be developed, which comes bundled with a p2p module and possible to execute docker containers or virtual environments across selected nodes. This project aims to create a peer to peer (p2p) network, where a user can use the p2p network to act as a client (i.e sending tasks) or the server (i.e executing the tasks). A prototype application will be developed, which comes bundled with a p2p module and possible to execute docker containers or virtual environments across selected nodes.
@@ -49,21 +72,37 @@ This project aims to create a peer to peer (p2p) network, where a user can use t
```go ```go
package main package main
import "github.com/Akilan1999/p2p-rendering-computation/abstractions" import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/abstractions"
)
func main() { func main() {
// Initialize with base p2prc config files _, err := abstractions.Init(nil)
err := abstractions.Init("TEST") if err != nil {
if err != nil { fmt.Println(err)
return return
} }
// start p2prc // start p2prc
_, err = abstractions.Start() _, err = abstractions.Start()
if err != nil { if err != nil {
return fmt.Println(err)
} return
}
// Run server till termination
for {
}
} }
```
### Export once this is added export P2PRC as environment paths
```
export P2PRC=<PROJECT PATH>
export PATH=<PROJECT PATH>:${PATH}
``` ```
[Read more](Docs/Abstractions.md) ... [Read more](Docs/Abstractions.md) ...
@@ -123,4 +162,3 @@ or just providing feedback on new features to build or even just curious about
[![Support Server](https://discordapp.com/api/guilds/854397492795277322/widget.png?style=banner2)](https://discord.gg/b4nRGTjYqy) [![Support Server](https://discordapp.com/api/guilds/854397492795277322/widget.png?style=banner2)](https://discord.gg/b4nRGTjYqy)
[![Star History Chart](https://api.star-history.com/svg?repos=Akilan1999/p2p-rendering-computation&type=Date)](https://github.com/Gaurav-Gosain) [![Star History Chart](https://api.star-history.com/svg?repos=Akilan1999/p2p-rendering-computation&type=Date)](https://github.com/Gaurav-Gosain)

88
abstractions/base.go Normal file
View File

@@ -0,0 +1,88 @@
package abstractions
import "C"
import (
"github.com/Akilan1999/p2p-rendering-computation/client"
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
Config "github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/config/generate"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
"github.com/Akilan1999/p2p-rendering-computation/server"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"github.com/gin-gonic/gin"
"os"
)
// Init Initialises p2prc
func Init(customConfig interface{}) (config *Config.Config, err error) {
// Get config file path
// Checks P2PRC path initially
// - Get PATH if environment varaible
path, err := Config.GetPathP2PRC("P2PRC")
if err != nil {
return
}
// check if the config file exists
if _, err = os.Stat(path + "config.json"); err != nil {
// Initialize with base p2prc config files
// set the config file with default paths
config, err = generate.SetDefaults("P2PRC", false, customConfig, false)
if err != nil {
return
}
} else {
// If the configs are available then use them over generating new ones.
config, err = Config.ConfigInit(nil, nil)
if err != nil {
return
}
}
return
}
// Start p2prc in a server mode
func Start() (*gin.Engine, error) {
engine, err := server.Server()
if err != nil {
return nil, err
}
return engine, nil
}
// MapPort Creates a reverse proxy connection and maps the appropriate port
func MapPort(port string) (entireAddres string, mapPort string, err error) {
entireAddres, mapPort, err = server.MapPort(port)
return
}
// StartContainer Starts docker container on the remote machine
func StartContainer(IP string) (container *docker.DockerVM, err error) {
container, err = client.StartContainer(IP, 0, false, "", "")
return
}
// RemoveContainer Removes docker container based on the IP address and ID
// provided
func RemoveContainer(IP string, ID string) error {
return client.RemoveContianer(IP, ID)
}
// GetSpecs Get spec information about the remote server
func GetSpecs(IP string) (specs *server.SysInfo, err error) {
specs, err = client.GetSpecs(IP)
return
}
// ViewIPTable View information of nodes in the network
func ViewIPTable() (table *p2p.IpAddresses, err error) {
table, err = p2p.ReadIpTable()
return
}
// UpdateIPTable Force updates IP tables based on new
// new nodes discovered in the network
func UpdateIPTable() (err error) {
return clientIPTable.UpdateIpTableListClient()
}

View File

@@ -1,27 +0,0 @@
package abstractions
import (
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/config/generate"
"github.com/Akilan1999/p2p-rendering-computation/server"
"github.com/gin-gonic/gin"
)
// Init Initialises p2prc
func Init(name string, customConfig interface{}) (config *config.Config, err error) {
// set the config file with default paths
config, err = generate.SetDefaults(name, false, customConfig, false)
if err != nil {
return
}
return
}
// Start p2prc in a server mode
func Start() (*gin.Engine, error) {
engine, err := server.Server()
if err != nil {
return nil, err
}
return engine, nil
}

BIN
artwork/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -4,13 +4,11 @@
## Pure HTML Version of the p2prc Logo :) ## Pure HTML Version of the p2prc Logo :)
![p2prc Logo](https://user-images.githubusercontent.com/55647468/204634868-07e94b6d-65f5-4446-a11f-7a14f11edff9.png) ![p2prc Logo](https://user-images.githubusercontent.com/55647468/204634868-07e94b6d-65f5-4446-a11f-7a14f11edff9.png)
> Note: To change the size of the logo simply edit the CSS variable of `--size` under the `style` tag! > [!NOTE]
> To change the size of the logo simply edit the CSS variable of `--size` under the `style` tag!
--- ---
### Embedding the HTML as a `foreignObject` element inside an SVG directly ### Embedding the HTML as a `foreignObject` element inside an SVG directly
![](embed.svg) ![](embed.svg)

1
build-bindings.sh Normal file
View File

@@ -0,0 +1 @@
cd Bindings && go build -buildmode=c-shared -o p2prc.so

28
build-python-package.sh Normal file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/bash
# Create export directory for python
mkdir Bindings/python/export
# Creating SharedObjects directory for python
mkdir Bindings/python/export/SharedObjects
sh build-bindings.sh
cp Bindings/p2prc.h Bindings/python/export/SharedObjects/
cp Bindings/p2prc.so Bindings/python/export/SharedObjects/
cp Bindings/python/p2prc.py Bindings/python/export/
echo "Output is in the Directory Bindings/python/export/"
# Architectures for Linux
#archs=(amd64 arm64)
#
#for arch in ${archs[@]}
#do
# mkdir Bindings/python/export/SharedObjects/linux-${arch}
# cd Bindings/
# env GOOS=linux GOARCH=${arch} go build -buildmode=c-shared -o python/export/SharedObjects/linux-${arch}/p2prc.so
# echo "GOOS=linux GOARCH=${arch} go build -buildmode=c-shared -o python/export/SharedObjects/linux-${arch}/p2prc.so"
# cd ..
#done

32
client/MAPPort.go Normal file
View File

@@ -0,0 +1,32 @@
package client
import (
"github.com/Akilan1999/p2p-rendering-computation/config"
"io/ioutil"
"net/http"
)
func MAPPort(port string) (string, error) {
Config, err := config.ConfigInit(nil, nil)
if err != nil {
return "", err
}
//if version == "version 6" {
URL := "http://0.0.0.0:" + Config.ServerPort + "/MAPPort?port=" + port
//} else {
// URL = "http://" + IP + ":" + serverPort + "/server_info"
//}
resp, err := http.Get(URL)
if err != nil {
return "", err
}
// Convert response to byte value
byteValue, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(byteValue), nil
}

View File

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

View File

@@ -150,6 +150,15 @@ func UpdateIpTableListClient() error {
return nil 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 // SendPostRequest Sends a file as a
//POST request. //POST request.
// Reference (https://stackoverflow.com/questions/51234464/upload-a-file-with-post-request-golang) // Reference (https://stackoverflow.com/questions/51234464/upload-a-file-with-post-request-golang)

View File

@@ -1,8 +1,10 @@
package client package client
import ( import (
b64 "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"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/server/docker" "github.com/Akilan1999/p2p-rendering-computation/server/docker"
"io/ioutil" "io/ioutil"
@@ -19,7 +21,7 @@ var (
// From the selected server IP address // From the selected server IP address
// TODO: Test cases for this function // TODO: Test cases for this function
// Calls URL ex: http://0.0.0.0:8088/startcontainer?ports=0&GPU=false&ContainerName=docker-ubuntu-sshd // Calls URL ex: http://0.0.0.0:8088/startcontainer?ports=0&GPU=false&ContainerName=docker-ubuntu-sshd
func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string) (*docker.DockerVM, error) { func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string, baseImage string) (*docker.DockerVM, error) {
// Passes URL with number of TCP ports to allocated and to give GPU access to the docker container // Passes URL with number of TCP ports to allocated and to give GPU access to the docker container
var URL string var URL string
//version := p2p.Ip4or6(IP) //version := p2p.Ip4or6(IP)
@@ -33,9 +35,22 @@ func StartContainer(IP string, NumPorts int, GPU bool, ContainerName string) (*d
//if version == "version 6" { //if version == "version 6" {
// URL = "http://[" + IP + "]:" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName // URL = "http://[" + IP + "]:" + serverPort + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName
//} else { //} else {
URL = "http://" + IP + "/startcontainer?ports=" + fmt.Sprint(NumPorts) + "&GPU=" + strconv.FormatBool(GPU) + "&ContainerName=" + ContainerName // Get config information
//} Config, err := config.ConfigInit(nil, nil)
if err != nil {
return nil, err
}
// Get public key
PublicKey, err := Config.GetPublicKey()
if err != nil {
return nil, err
}
// Used in URL to pass public key -> b64.StdEncoding.EncodeToString([]byte(PublicKey))
URL = `http://` + IP + `/startcontainer?ports=` + fmt.Sprint(NumPorts) + `&GPU=` + strconv.FormatBool(GPU) + `&ContainerName=` + ContainerName + `&BaseImage=` + baseImage + `&PublicKey=` + b64.StdEncoding.EncodeToString([]byte(PublicKey))
// Encode URL due to public key passed.
resp, err := http.Get(URL) resp, err := http.Get(URL)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -1,277 +1,298 @@
package cmd package cmd
import ( import (
"fmt" "fmt"
"github.com/Akilan1999/p2p-rendering-computation/client" "github.com/Akilan1999/p2p-rendering-computation/client"
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable" "github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
"github.com/Akilan1999/p2p-rendering-computation/config/generate" "github.com/Akilan1999/p2p-rendering-computation/config/generate"
"github.com/Akilan1999/p2p-rendering-computation/p2p" "github.com/Akilan1999/p2p-rendering-computation/p2p"
"github.com/Akilan1999/p2p-rendering-computation/plugin" "github.com/Akilan1999/p2p-rendering-computation/plugin"
"github.com/Akilan1999/p2p-rendering-computation/server" "github.com/Akilan1999/p2p-rendering-computation/server"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var CliAction = func(ctx *cli.Context) error { var CliAction = func(ctx *cli.Context) error {
if Server { if Server {
_, err := server.Server() _, err := server.Server()
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
} }
//server.Rpc() //server.Rpc()
for { for {
} }
} }
//Listing servers and also updates IP tables (Default 3 hops) //Listing servers and also updates IP tables (Default 3 hops)
if UpdateServerList { if UpdateServerList {
err := clientIPTable.UpdateIpTableListClient() err := clientIPTable.UpdateIpTableListClient()
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
} }
// Reads from ip table and passes it // Reads from ip table and passes it
// on to struct print function // on to struct print function
//Servers, err := p2p.ReadIpTable() //Servers, err := p2p.ReadIpTable()
//if err != nil { //if err != nil {
// return err // return err
//} //}
//client.PrettyPrint(Servers) //client.PrettyPrint(Servers)
p2p.PrintIpTable() p2p.PrintIpTable()
} }
// Displays the IP table // Displays the IP table
if ServerList { if ServerList {
// Reads from ip table and passes it // Reads from ip table and passes it
// on to struct print function // on to struct print function
//Servers, err := p2p.ReadIpTable() //Servers, err := p2p.ReadIpTable()
//if err != nil { //if err != nil {
// return err // return err
//} //}
p2p.PrintIpTable() p2p.PrintIpTable()
} }
// Add provided IP to the IP table // Add provided IP to the IP table
if AddServer != "" { if AddServer != "" {
res, err := p2p.ReadIpTable() res, err := p2p.ReadIpTable()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
//Create variable of type IpAddress and set IP address //Create variable of type IpAddress and set IP address
// to it // to it
var IpAddr p2p.IpAddress var IpAddr p2p.IpAddress
//Checking if the address is a ipv4 //Checking if the address is a ipv4
// or ipv6 address // or ipv6 address
ip4Orip6 := p2p.Ip4or6(AddServer) ip4Orip6 := p2p.Ip4or6(AddServer)
if ip4Orip6 == "version 6" { if ip4Orip6 == "version 6" {
IpAddr.Ipv6 = AddServer IpAddr.Ipv6 = AddServer
} else { } else {
IpAddr.Ipv4 = AddServer IpAddr.Ipv4 = AddServer
} }
// If a server port is provided then set it // If a server port is provided then set it
if Ports != "" { if Ports != "" {
IpAddr.ServerPort = Ports IpAddr.ServerPort = Ports
} else { } else {
IpAddr.ServerPort = "8088" IpAddr.ServerPort = "8088"
} }
// Append IP address to variable result which // Append IP address to variable result which
// is a list // is a list
res.IpAddress = append(res.IpAddress, IpAddr) res.IpAddress = append(res.IpAddress, IpAddr)
// Adds the new server IP to the iptable // Adds the new server IP to the iptable
res.WriteIpTable() res.WriteIpTable()
} }
// Displays all images available on the server side // Displays all images available on the server side
if ViewImages != "" { if ViewImages != "" {
imageRes, err := client.ViewContainers(ViewImages) imageRes, err := client.ViewContainers(ViewImages)
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
} }
client.PrettyPrint(imageRes) client.PrettyPrint(imageRes)
} }
// Function called to stop and remove server from Docker // Function called to stop and remove server from Docker
if RemoveVM != "" { if RemoveVM != "" {
if ID == "" { if ID == "" {
fmt.Println("provide container ID via --ID or --id") fmt.Println("provide container ID via --ID or --id")
} else { } else {
err := client.RemoveContianer(RemoveVM, ID) err := client.RemoveContianer(RemoveVM, ID)
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
} }
} }
} }
//Call function to create Docker container //Call function to create Docker container
if CreateVM != "" { if CreateVM != "" {
var PortsInt int var PortsInt int
if Ports != "" { if Ports != "" {
// Convert Get Request value to int // Convert Get Request value to int
fmt.Sscanf(Ports, "%d", &PortsInt) fmt.Sscanf(Ports, "%d", &PortsInt)
} }
// Calls function to do Api call to start the container on the server side // Calls function to do Api call to start the container on the server side
imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName) imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName, BaseImage)
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
} }
client.PrettyPrint(imageRes) client.PrettyPrint(imageRes)
} }
//Call if specs flag is called //Call if specs flag is called
if Specs != "" { if Specs != "" {
specs, err := client.GetSpecs(Specs) specs, err := client.GetSpecs(Specs)
if err != nil { if err != nil {
return err return err
} }
// Pretty print // Pretty print
client.PrettyPrint(specs) client.PrettyPrint(specs)
} }
//Sets default paths to the config file //Sets default paths to the config file
if SetDefaultConfig { if SetDefaultConfig {
_, err := generate.SetDefaults("P2PRC", false, nil, false) _, err := generate.SetDefaults("P2PRC", false, nil, false)
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
} }
} }
//If the network interface flag is called //If the network interface flag is called
// Then all the network interfaces are displayed // Then all the network interfaces are displayed
if NetworkInterface { if NetworkInterface {
err := p2p.ViewNetworkInterface() err := p2p.ViewNetworkInterface()
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
} }
} }
// If the view plugin flag is called then display all // If the view plugin flag is called then display all
// plugins available // plugins available
if ViewPlugin { if ViewPlugin {
plugins, err := plugin.DetectPlugins() plugins, err := plugin.DetectPlugins()
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
} }
client.PrettyPrint(plugins) client.PrettyPrint(plugins)
} }
// If the flag Tracked Container is called or the flag // If the flag Tracked Container is called or the flag
// --tc // --tc
if TrackedContainers { if TrackedContainers {
err, trackedContainers := client.ViewTrackedContainers() err, trackedContainers := client.ViewTrackedContainers()
if err != nil { if err != nil {
fmt.Print(err) fmt.Print(err)
} }
client.PrettyPrint(trackedContainers) client.PrettyPrint(trackedContainers)
} }
//Executing plugin when the plugin flag is called //Executing plugin when the plugin flag is called
// --plugin // --plugin
if ExecutePlugin != "" { if ExecutePlugin != "" {
// To execute plugin requires the container ID or group ID provided when being executed // To execute plugin requires the container ID or group ID provided when being executed
if ID != "" { if ID != "" {
err := plugin.CheckRunPlugin(ExecutePlugin, ID) err := plugin.CheckRunPlugin(ExecutePlugin, ID)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} else { } else {
fmt.Println("Success") fmt.Println("Success")
} }
} else { } else {
fmt.Println("provide container ID via --ID or --id") fmt.Println("provide container ID via --ID or --id")
} }
} }
// Executing function to create new group // Executing function to create new group
// Creates new group and outputs JSON file // Creates new group and outputs JSON file
if CreateGroup { if CreateGroup {
group, err := client.CreateGroup() group, err := client.CreateGroup()
if err != nil { if err != nil {
return err return err
} }
client.PrettyPrint(group) client.PrettyPrint(group)
} }
// Actions to be performed when the // Actions to be performed when the
// group flag is called // group flag is called
// --group <Group ID> // --group <Group ID>
if Group != "" { if Group != "" {
// Remove container from group based on group ID provided // Remove container from group based on group ID provided
// --rmcgroup --id <contianer id> // --rmcgroup --id <contianer id>
if RemoveContainerGroup && ID != "" { if RemoveContainerGroup && ID != "" {
group, err := client.RemoveContainerGroup(ID, Group) group, err := client.RemoveContainerGroup(ID, Group)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} else { } else {
client.PrettyPrint(group) client.PrettyPrint(group)
} }
} else if ID != "" { // Add container to group based on group ID provided } else if ID != "" { // Add container to group based on group ID provided
// --id <Container ID> // --id <Container ID>
group, err := client.AddContainerToGroup(ID, Group) group, err := client.AddContainerToGroup(ID, Group)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} else { } else {
client.PrettyPrint(group) client.PrettyPrint(group)
} }
} else { // View all information about current group } else { // View all information about current group
group, err := client.GetGroup(Group) group, err := client.GetGroup(Group)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} else { } else {
client.PrettyPrint(group) client.PrettyPrint(group)
} }
} }
} }
// Execute function to remove entire group // Execute function to remove entire group
// when remove group flag is called // when remove group flag is called
// --rmgroup // --rmgroup
if RemoveGroup != "" { if RemoveGroup != "" {
err := client.RemoveGroup(RemoveGroup) err := client.RemoveGroup(RemoveGroup)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} else { } else {
fmt.Println("Group Removed") fmt.Println("Group Removed")
} }
} }
// Execute Function to view all groups // Execute Function to view all groups
if Groups { if Groups {
groups, err := client.ReadGroup() groups, err := client.ReadGroup()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} else { } else {
client.PrettyPrint(groups) client.PrettyPrint(groups)
} }
} }
//-------------------------------- //--------------------------------
if PullPlugin != "" { if PullPlugin != "" {
err := plugin.DownloadPlugin(PullPlugin) err := plugin.DownloadPlugin(PullPlugin)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} else { } else {
fmt.Println("Success") fmt.Println("Success")
} }
} }
if RemovePlugin != "" { if RemovePlugin != "" {
err := plugin.DeletePlugin(RemovePlugin) err := plugin.DeletePlugin(RemovePlugin)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} else { } else {
fmt.Println("Success") fmt.Println("Success")
} }
} }
return nil if AddMetaData != "" {
err := clientIPTable.AddCustomInformationToIPTable(AddMetaData)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Success")
}
}
if MAPPort != "" {
address, err := client.MAPPort(MAPPort)
if err != nil {
return err
}
if err != nil {
fmt.Println(err)
} else {
fmt.Println(address)
}
}
return nil
} }

View File

@@ -10,6 +10,7 @@ var (
ViewImages string ViewImages string
CreateVM string CreateVM string
ContainerName string ContainerName string
BaseImage string
Ports string Ports string
Server bool Server bool
RemoveVM string RemoveVM string
@@ -28,6 +29,7 @@ var (
Groups bool Groups bool
RemoveContainerGroup bool RemoveContainerGroup bool
RemoveGroup string RemoveGroup string
MAPPort string
//FRPProxy bool //FRPProxy bool
// Generate only allowed in dev release // Generate only allowed in dev release
// -- REMOVE ON REGULAR RELEASE -- // -- REMOVE ON REGULAR RELEASE --
@@ -36,6 +38,7 @@ var (
//-------------------------------- //--------------------------------
PullPlugin string PullPlugin string
RemovePlugin string RemovePlugin string
AddMetaData string
) )
var AppConfigFlags = []cli.Flag{ var AppConfigFlags = []cli.Flag{
@@ -89,6 +92,13 @@ var AppConfigFlags = []cli.Flag{
EnvVars: []string{"CONTAINER_NAME"}, EnvVars: []string{"CONTAINER_NAME"},
Destination: &ContainerName, Destination: &ContainerName,
}, },
&cli.StringFlag{
Name: "BaseImage",
Aliases: []string{"bi"},
Usage: "Specifying the docker base image to template the dockerfile",
EnvVars: []string{"CONTAINER_NAME"},
Destination: &BaseImage,
},
&cli.StringFlag{ &cli.StringFlag{
Name: "RemoveVM", Name: "RemoveVM",
Aliases: []string{"rm"}, Aliases: []string{"rm"},
@@ -195,6 +205,13 @@ var AppConfigFlags = []cli.Flag{
EnvVars: []string{"REMOVE_GROUP"}, EnvVars: []string{"REMOVE_GROUP"},
Destination: &RemoveGroup, Destination: &RemoveGroup,
}, },
&cli.StringFlag{
Name: "MAPPort",
Aliases: []string{"mp"},
Usage: "Maps port for a specific port provided as the parameter",
EnvVars: []string{"MAPPORT"},
Destination: &MAPPort,
},
// Generate only allowed in dev release // Generate only allowed in dev release
// -- REMOVE ON REGULAR RELEASE -- // -- REMOVE ON REGULAR RELEASE --
&cli.StringFlag{ &cli.StringFlag{
@@ -233,4 +250,11 @@ var AppConfigFlags = []cli.Flag{
EnvVars: []string{"REMOVEPLUGIN"}, EnvVars: []string{"REMOVEPLUGIN"},
Destination: &RemovePlugin, Destination: &RemovePlugin,
}, },
&cli.StringFlag{
Name: "AddMetaData",
Aliases: []string{"amd"},
Usage: "Adds metadata about the current node in the p2p network which is then propagated through the network",
EnvVars: []string{"ADDMETADATA"},
Destination: &AddMetaData,
},
} }

View File

@@ -1,52 +1,66 @@
package config package config
import ( import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"os" "os"
) )
var ( var (
//defaultPath string //defaultPath string
defaults = map[string]interface{}{} defaults = map[string]interface{}{}
configName = "config" configName = "config"
configType = "json" configType = "json"
configFile = "config.json" configFile = "config.json"
configPaths []string configPaths []string
defaultEnvName = "P2PRC" defaultEnvName = "P2PRC"
) )
type Config struct { type Config struct {
MachineName string MachineName string
IPTable string IPTable string
DockerContainers string DockerContainers string
DefaultDockerFile string DefaultDockerFile string
SpeedTestFile string DockerRunLogs string
IPV6Address string SpeedTestFile string
PluginPath string IPV6Address string
TrackContainersPath string PluginPath string
ServerPort string TrackContainersPath string
GroupTrackContainersPath string ServerPort string
FRPServerPort string GroupTrackContainersPath string
BehindNAT string FRPServerPort string
CustomConfig interface{} BehindNAT string
//NetworkInterface string IPTableKey string
//NetworkInterfaceIPV6Index int PublicKeyFile string
PrivateKeyFile string
BareMetal string
CustomConfig interface{}
//NetworkInterface string
//NetworkInterfaceIPV6Index int
}
// GetCurrentPath Getting P2PRC Directory from environment variable
func GetCurrentPath() (string, error) {
curDir := os.Getenv("PWD")
return curDir + "/", nil
} }
// GetPathP2PRC Getting P2PRC Directory from environment variable // GetPathP2PRC Getting P2PRC Directory from environment variable
func GetPathP2PRC(Envname string) (string, error) { func GetPathP2PRC(Envname string) (string, error) {
if Envname != "" { if Envname != "" {
err := SetEnvName(Envname) err := SetEnvName(Envname)
if err != nil { if err != nil {
return "", err return "", err
} }
} }
curDir := os.Getenv(defaultEnvName) curDir := os.Getenv(defaultEnvName)
if curDir == "" { if curDir == "" {
return curDir, nil // if the OS env path is not found then you use
} // the current directory path.
return curDir + "/", nil currentPath, _ := GetCurrentPath()
return currentPath, nil
}
return curDir + "/", nil
} }
// SetEnvName Sets the environment name // SetEnvName Sets the environment name
@@ -54,103 +68,114 @@ func GetPathP2PRC(Envname string) (string, error) {
// your environment variable // your environment variable
// This is useful when extending the use case of P2PRC // This is useful when extending the use case of P2PRC
func SetEnvName(EnvName string) error { func SetEnvName(EnvName string) error {
defaultEnvName = EnvName defaultEnvName = EnvName
// Handling error to be implemented only if needed // Handling error to be implemented only if needed
return nil return nil
} }
func GetEnvName() string { func GetEnvName() string {
return defaultEnvName return defaultEnvName
} }
// ConfigInit Pass environment name as an optional parameter // ConfigInit Pass environment name as an optional parameter
func ConfigInit(defaultsParameter map[string]interface{}, CustomConfig interface{}, envNameOptional ...string) (*Config, error) { func ConfigInit(defaultsParameter map[string]interface{}, CustomConfig interface{}, envNameOptional ...string) (*Config, error) {
if len(envNameOptional) > 0 { if len(envNameOptional) > 0 {
defaultEnvName = envNameOptional[0] defaultEnvName = envNameOptional[0]
} }
// //
////Setting current directory to default path ////Setting current directory to default path
//defaultPath, err := GetPathP2PRC(defaultEnvName) //defaultPath, err := GetPathP2PRC(defaultEnvName)
//if err != nil { //if err != nil {
// return nil, err // return nil, err
//} //}
////Paths to search for config file ////Paths to search for config file
//configPaths = append(configPaths, defaultPath) //configPaths = append(configPaths, defaultPath)
// //
////Add all possible configurations paths ////Add all possible configurations paths
//for _, v := range configPaths { //for _, v := range configPaths {
// viper.AddConfigPath(v) // viper.AddConfigPath(v)
//} //}
// //
////Read config file ////Read config file
//if err := viper.ReadInConfig(); err != nil { //if err := viper.ReadInConfig(); err != nil {
// // If the error thrown is config file not found // // If the error thrown is config file not found
// //Sets default configuration to viper // //Sets default configuration to viper
// for k, v := range defaults { // for k, v := range defaults {
// viper.SetDefault(k, v) // viper.SetDefault(k, v)
// } // }
// viper.SetConfigName(configName) // viper.SetConfigName(configName)
// viper.SetConfigFile(configFile) // viper.SetConfigFile(configFile)
// viper.SetConfigType(configType) // viper.SetConfigType(configType)
// //
// if err = viper.WriteConfig(); err != nil { // if err = viper.WriteConfig(); err != nil {
// return nil, err // return nil, err
// } // }
//} //}
// //
//// Adds configuration to the struct //// Adds configuration to the struct
//var config Config //var config Config
//if err := viper.Unmarshal(&config); err != nil { //if err := viper.Unmarshal(&config); err != nil {
// return nil, err // return nil, err
//} //}
// //
//return &config, nil //return &config, nil
defaultPath, err := GetPathP2PRC(defaultEnvName) defaultPath, err := GetPathP2PRC(defaultEnvName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Open our jsonFile // Open our jsonFile
jsonFile, err := os.Open(defaultPath + configFile) jsonFile, err := os.Open(defaultPath + configFile)
// 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()
byteValue, _ := ioutil.ReadAll(jsonFile) byteValue, _ := ioutil.ReadAll(jsonFile)
var config Config var config Config
json.Unmarshal(byteValue, &config) json.Unmarshal(byteValue, &config)
if CustomConfig != nil { if CustomConfig != nil {
// Convert Custom Config to byte // Convert Custom Config to byte
customConfigByte, err := json.Marshal(config.CustomConfig) customConfigByte, err := json.Marshal(config.CustomConfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Again map the byte to the CustomConfig interface // Again map the byte to the CustomConfig interface
json.Unmarshal(customConfigByte, &CustomConfig) json.Unmarshal(customConfigByte, &CustomConfig)
} }
return &config, nil return &config, nil
} }
func (c *Config) WriteConfig() error { func (c *Config) WriteConfig() error {
//Getting Current Directory from environment variable //Getting Current Directory from environment variable
//curDir := os.Getenv("REMOTEGAMING") //curDir := os.Getenv("REMOTEGAMING")
defaultPath, err := GetPathP2PRC(defaultEnvName) defaultPath, err := GetPathP2PRC(defaultEnvName)
if err != nil { if err != nil {
return err return err
} }
file, _ := json.MarshalIndent(c, "", " ") file, _ := json.MarshalIndent(c, "", " ")
_ = ioutil.WriteFile(defaultPath+"config.json", file, 0644) _ = ioutil.WriteFile(defaultPath+"config.json", file, 0644)
return nil return nil
}
// GetPublicKey Gets public key of the current machine
// based on the path provided on the
// config file
func (c *Config) GetPublicKey() (string, error) {
publicKey, err := ioutil.ReadFile(c.PublicKeyFile) // just pass the file name
if err != nil {
return "", err
}
return string(publicKey), nil
} }

View File

@@ -1,20 +1,22 @@
package generate package generate
import ( import (
"github.com/Akilan1999/p2p-rendering-computation/config" "github.com/Akilan1999/p2p-rendering-computation/config"
"os" "math/rand"
"os"
"time"
) )
var ( var (
defaults = map[string]interface{}{} defaults = map[string]interface{}{}
configPaths []string configPaths []string
defaultEnvName = "P2PRC" defaultEnvName = "P2PRC"
) )
// GetPathP2PRC Getting P2PRC Directory from environment variable // GetPathP2PRC Getting P2PRC Directory from environment variable
func GetPathP2PRC() (string, error) { func GetPathP2PRC() (string, error) {
curDir := os.Getenv(defaultEnvName) curDir := os.Getenv(defaultEnvName)
return curDir + "/", nil return curDir + "/", nil
} }
// SetEnvName Sets the environment name // SetEnvName Sets the environment name
@@ -22,110 +24,144 @@ func GetPathP2PRC() (string, error) {
// your environment variable // your environment variable
// This is useful when extending the use case of P2PRC // This is useful when extending the use case of P2PRC
func SetEnvName(EnvName string) error { func SetEnvName(EnvName string) error {
if EnvName != "" { if EnvName != "" {
defaultEnvName = EnvName defaultEnvName = EnvName
} }
// Handling error to be implemented only if needed // Handling error to be implemented only if needed
return nil return nil
}
// GetCurrentPath Getting P2PRC Directory from environment variable
func GetCurrentPath() (string, error) {
curDir := os.Getenv("PWD")
return curDir + "/", nil
} }
// SetDefaults This function to be called only during a // SetDefaults This function to be called only during a
// make install // make install
func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, NoBoilerPlate bool, ConfigUpdate ...*config.Config) (*config.Config, error) { func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, NoBoilerPlate bool, ConfigUpdate ...*config.Config) (*config.Config, error) {
//Setting current directory to default path //Setting current directory to default path
defaultPath, err := GetCurrentPath() defaultPath, err := config.GetCurrentPath()
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Set Env name // Set Env name
err = config.SetEnvName(envName) err = config.SetEnvName(envName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
////Creates ip_table.json in the json directory ////Creates ip_table.json in the json directory
//err = Copy("p2p/ip_table.json", "p2p/iptable/ip_table.json") //err = Copy("p2p/ip_table.json", "p2p/iptable/ip_table.json")
//if err != nil { //if err != nil {
// return err // return err
//} //}
// //
////Creates a copy of trackcontainers.json in the appropriate directory ////Creates a copy of trackcontainers.json in the appropriate directory
//err = Copy("client/trackcontainers.json", "client/trackcontainers/trackcontainers.json") //err = Copy("client/trackcontainers.json", "client/trackcontainers/trackcontainers.json")
//if err != nil { //if err != nil {
// return err // return err
//} //}
// //
////Creates a copy of trackcontainers.json in the appropriate directory ////Creates a copy of trackcontainers.json in the appropriate directory
//err = Copy("client/grouptrackcontainers.json", "client/trackcontainers/grouptrackcontainers.json") //err = Copy("client/grouptrackcontainers.json", "client/trackcontainers/grouptrackcontainers.json")
//if err != nil { //if err != nil {
// return err // return err
//} //}
var Defaults config.Config var Defaults config.Config
if len(ConfigUpdate) == 0 { if len(ConfigUpdate) == 0 {
//Setting default paths for the config file //Setting default paths for the config file
Defaults.IPTable = defaultPath + "p2p/iptable/ip_table.json" Defaults.IPTable = defaultPath + "p2p/iptable/ip_table.json"
Defaults.DefaultDockerFile = defaultPath + "server/docker/containers/docker-ubuntu-sshd/" Defaults.DefaultDockerFile = defaultPath + "server/docker/containers/docker-ubuntu-sshd/"
Defaults.DockerContainers = defaultPath + "server/docker/containers/" Defaults.DockerContainers = defaultPath + "server/docker/containers/"
Defaults.SpeedTestFile = defaultPath + "p2p/50.bin" Defaults.SpeedTestFile = defaultPath + "p2p/50.bin"
Defaults.IPV6Address = "" Defaults.IPV6Address = ""
Defaults.PluginPath = defaultPath + "plugin/deploy" Defaults.PluginPath = defaultPath + "plugin/deploy"
Defaults.TrackContainersPath = defaultPath + "client/trackcontainers/trackcontainers.json" Defaults.TrackContainersPath = defaultPath + "client/trackcontainers/trackcontainers.json"
Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json" Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json"
Defaults.ServerPort = "8088" Defaults.ServerPort = "8088"
Defaults.FRPServerPort = "True" Defaults.FRPServerPort = "True"
Defaults.CustomConfig = CustomConfig Defaults.CustomConfig = CustomConfig
Defaults.BehindNAT = "True" Defaults.BehindNAT = "True"
// Random name generator Defaults.DockerRunLogs = "/tmp/"
hostname, err := os.Hostname() // Generate a random key to be added to IPTable
if err != nil { Defaults.IPTableKey = String(12)
return nil, err // Random name generator
} hostname, err := os.Hostname()
if err != nil {
return nil, err
}
Defaults.MachineName = hostname // Generate Public and private keys and set path
} else { Defaults.PublicKeyFile = defaultPath + "p2prc.PublicKeyBareMetal"
Defaults = *ConfigUpdate[0] Defaults.PrivateKeyFile = defaultPath + "p2prc.privateKey"
} Defaults.BareMetal = "False"
//defaults["NetworkInterface"] = "wlp0s20f3" PrivateKeyExists, err := FileExists(Defaults.PrivateKeyFile)
//defaults["NetworkInterfaceIPV6Index"] = "2" if err != nil {
return nil, err
}
//Paths to search for config file if !PrivateKeyExists {
configPaths = append(configPaths, defaultPath) // Generate SSH keys
err = MakeSSHKeyPair(Defaults.PublicKeyFile, Defaults.PrivateKeyFile)
if err != nil {
return nil, err
}
}
if fileExists(defaultPath+"config.json") && forceDefault { Defaults.MachineName = hostname + "-" + String(7)
err := os.Remove(defaultPath + "config.json") } else {
if err != nil { Defaults = *ConfigUpdate[0]
return nil, err }
}
}
// write defaults to the config file //defaults["NetworkInterface"] = "wlp0s20f3"
err = Defaults.WriteConfig() //defaults["NetworkInterfaceIPV6Index"] = "2"
if err != nil {
return nil, err
}
//Calling configuration file //Paths to search for config file
Config, err := config.ConfigInit(defaults, nil, envName) configPaths = append(configPaths, defaultPath)
if err != nil {
return nil, err
}
if !NoBoilerPlate { if fileExists(defaultPath+"config.json") && forceDefault {
err = GenerateFiles() err := os.Remove(defaultPath + "config.json")
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
return Config, nil // write defaults to the config file
err = Defaults.WriteConfig()
if err != nil {
return nil, err
}
//Calling configuration file
Config, err := config.ConfigInit(defaults, nil, envName)
if err != nil {
return nil, err
}
if !NoBoilerPlate {
err = GenerateFiles()
if err != nil {
return nil, err
}
}
return Config, nil
}
// Generating a random string
const charset = "abcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var seededRand *rand.Rand = rand.New(
rand.NewSource(time.Now().UnixNano()))
func StringWithCharset(length int, charset string) string {
b := make([]byte, length)
for i := range b {
b[i] = charset[seededRand.Intn(len(charset))]
}
return string(b)
}
func String(length int) string {
return StringWithCharset(length, charset)
} }

View File

@@ -1,16 +1,32 @@
package generate package generate
import ( import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/p2p" "github.com/Akilan1999/p2p-rendering-computation/p2p"
"github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5"
"golang.org/x/crypto/ssh"
"io/ioutil"
"os" "os"
) )
// GenerateFiles Generates all the files needed to setup P2PRC // GenerateFiles Generates all the files needed to setup P2PRC
func GenerateFiles(rootNodes ...p2p.IpAddress) (err error) { func GenerateFiles(rootNodes ...p2p.IpAddress) (err error) {
err = GenerateIPTableFile(rootNodes) err = GenerateIPTableFile(rootNodes)
if err != nil {
return err
}
err = GenerateDockerFiles() err = GenerateDockerFiles()
if err != nil {
return err
}
err = GeneratePluginDirectory() err = GeneratePluginDirectory()
if err != nil {
return err
}
err = GenerateClientTrackContainers() err = GenerateClientTrackContainers()
return return
} }
@@ -28,9 +44,9 @@ func GenerateIPTableFile(rootNodes []p2p.IpAddress) (err error) {
// If root node addresses are not provided as optional parameters // If root node addresses are not provided as optional parameters
if len(rootNodes) <= 0 { if len(rootNodes) <= 0 {
rootnode.Name = "Node1" rootnode.Name = "Node1"
rootnode.ServerPort = "8088" rootnode.ServerPort = "8078"
rootnode.NAT = "False" rootnode.NAT = "False"
rootnode.Ipv4 = "64.227.168.102" rootnode.Ipv4 = "217.76.63.222"
rootnodes.IpAddress = append(rootnodes.IpAddress, rootnode) rootnodes.IpAddress = append(rootnodes.IpAddress, rootnode)
} else { } else {
@@ -46,7 +62,7 @@ func GenerateIPTableFile(rootNodes []p2p.IpAddress) (err error) {
// CreateIPTableFolderStructure Create folder structure for IPTable // CreateIPTableFolderStructure Create folder structure for IPTable
func CreateIPTableFolderStructure() (err error) { func CreateIPTableFolderStructure() (err error) {
path, err := GetCurrentPath() path, err := config.GetCurrentPath()
if err != nil { if err != nil {
return err return err
} }
@@ -72,7 +88,7 @@ func CreateIPTableFolderStructure() (err error) {
// GenerateDockerFiles Generate default docker files // GenerateDockerFiles Generate default docker files
func GenerateDockerFiles() (err error) { func GenerateDockerFiles() (err error) {
path, err := GetCurrentPath() path, err := config.GetCurrentPath()
if err != nil { if err != nil {
return err return err
} }
@@ -117,7 +133,7 @@ func GenerateDockerFiles() (err error) {
// GeneratePluginDirectory Generates plugin directory structure // GeneratePluginDirectory Generates plugin directory structure
func GeneratePluginDirectory() (err error) { func GeneratePluginDirectory() (err error) {
path, err := GetCurrentPath() path, err := config.GetCurrentPath()
if err != nil { if err != nil {
return err return err
} }
@@ -135,7 +151,7 @@ func GeneratePluginDirectory() (err error) {
} }
func GenerateClientTrackContainers() (err error) { func GenerateClientTrackContainers() (err error) {
path, err := GetCurrentPath() path, err := config.GetCurrentPath()
if err != nil { if err != nil {
return err return err
} }
@@ -143,16 +159,16 @@ func GenerateClientTrackContainers() (err error) {
if err = os.Mkdir(path+"client", os.ModePerm); err != nil { if err = os.Mkdir(path+"client", os.ModePerm); err != nil {
return err return err
} }
if err = os.Mkdir(path+"client/trackcontainers", os.ModePerm); err != nil {
return err
}
if _, err = os.Stat(path + "client/trackcontainers.json"); os.IsNotExist(err) { if _, err = os.Stat(path + "client/trackcontainers/trackcontainers.json"); os.IsNotExist(err) {
_, err = os.Create(path + "client/trackcontainers.json") _, err = os.Create(path + "client/trackcontainers/trackcontainers.json")
if err != nil { if err != nil {
return err return err
} }
} _, err = os.Create(path + "client/trackcontainers/grouptrackcontainers.json")
if _, err = os.Stat(path + "client/grouptrackcontainers.json"); os.IsNotExist(err) {
_, err = os.Create(path + "client/grouptrackcontainers.json")
if err != nil { if err != nil {
return err return err
} }
@@ -161,3 +177,114 @@ func GenerateClientTrackContainers() (err error) {
} }
return return
} }
// MakeSSHKeyPair make a pair of public and private keys for SSH access.
// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file.
// Private Key generated is PEM encoded
// source: https://gist.github.com/goliatone/e9c13e5f046e34cef6e150d06f20a34c
func MakeSSHKeyPair(pubKeyPath, privateKeyPath string) error {
privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
return err
}
// generate and write private key as PEM
privateKeyFile, err := os.Create(privateKeyPath)
defer privateKeyFile.Close()
if err != nil {
return err
}
// Set permission to private key to SSH into docker machine
err = os.Chmod(privateKeyPath, 600)
if err != nil {
return err
}
privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
if err := pem.Encode(privateKeyFile, privateKeyPEM); err != nil {
return err
}
// generate and write public key
pub, err := ssh.NewPublicKey(&privateKey.PublicKey)
if err != nil {
return err
}
return ioutil.WriteFile(pubKeyPath, ssh.MarshalAuthorizedKey(pub), 0655)
}
// FileExists exists returns whether the given file or directory exists
// source: https://stackoverflow.com/questions/10510691/how-to-check-whether-a-file-or-directory-exists
func FileExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// AuthorizedKey struct represents the structure of an authorized key
type AuthorizedKey struct {
Username string
Key string
}
// AddPublicKeyBareMetal Adds the parameter public key to the auth list
// Generated by ChatGPT
// Prompts:
// - Generate a go program to read authorised key and map it to a struct and write it back to the same location.
// - Can you follow the original format
// (TURNED OUT TO BE PRETTY SHITTY GENERATED CODE)
//func AddPublicKeyBareMetal(PublicKey string) error {
// // Specify the path to the authorized_keys file
// dirname, err := os.UserHomeDir()
// if err != nil {
// return err
// }
//
// authorizedKeysPath := dirname + "/.ssh/" + "authorized_keys"
//
// // Read the contents of the authorized_keys file
// file, err := os.Open(authorizedKeysPath)
// if err != nil {
// return err
// }
// defer file.Close()
//
// // Create a slice to store AuthorizedKey structs
// var authorizedKeys []AuthorizedKey
//
// // Read each line of the file and parse the data
// scanner := bufio.NewScanner(file)
// for scanner.Scan() {
// line := scanner.Text()
// parts := strings.Fields(line)
// if len(parts) >= 2 {
// authorizedKey := AuthorizedKey{
// Username: parts[0],
// Key: parts[1],
// }
// authorizedKeys = append(authorizedKeys, authorizedKey)
// }
// }
//
// if err := scanner.Err(); err != nil {
// return err
// }
//
// // Modify the slice of structs if needed
// // authorizedKeys[0].Username = "newUsername"
// // authorizedKeys[0].Key = "newKey"
// authorizedKeys = append(authorizedKeys, AuthorizedKey{Username: "", Key: PublicKey})
//
// // Write the modified data back to the authorized_keys file
// newFile, err := os.Create(authorizedKeysPath)
// if err != nil {
// return err
// }
// defer newFile.Close()
//
// return nil
//}

View File

@@ -1,35 +1,40 @@
package generate package generate
import ( import (
"fmt" "fmt"
"github.com/Akilan1999/p2p-rendering-computation/config" "github.com/Akilan1999/p2p-rendering-computation/config"
"testing" "testing"
) )
type CustomConfig struct { type CustomConfig struct {
Test string Test string
} }
// Test case to generate defaults with custom data-structure // Test case to generate defaults with custom data-structure
func TestSetDefaults(t *testing.T) { func TestSetDefaults(t *testing.T) {
setDefaults, err := SetDefaults("", true, &CustomConfig{Test: "lol"}, true) setDefaults, err := SetDefaults("", true, &CustomConfig{Test: "lol"}, true)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
return return
} }
fmt.Println(setDefaults) fmt.Println(setDefaults)
var c CustomConfig var c CustomConfig
_, err = config.ConfigInit(nil, &c) _, err = config.ConfigInit(nil, &c)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
t.Fail() t.Fail()
return return
} }
fmt.Println(c) fmt.Println(c)
} }
// Test case to generate public and private keys
func TestGeneratePublicAndPrivateKeys(t *testing.T) {
MakeSSHKeyPair("test.pub", "test.prv")
}

22
default.nix Normal file
View File

@@ -0,0 +1,22 @@
{ nixpkgs ? import <nixpkgs> { } }:
let
pkgs = [
nixpkgs.go
nixpkgs.tmux
nixpkgs.docker
nixpkgs.vim
];
in
nixpkgs.stdenv.mkDerivation {
name = "env";
buildInputs = pkgs;
pure-eval = true;
shellHook =
''
make
export P2PRC=$PWD
export PATH=$PWD:$PATH
'';
}

8
go.mod
View File

@@ -3,17 +3,16 @@ module github.com/Akilan1999/p2p-rendering-computation
go 1.15 go 1.15
require ( require (
github.com/Microsoft/hcsshim v0.8.15 // indirect github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 // indirect
github.com/apenella/go-ansible v1.1.0 github.com/apenella/go-ansible v1.1.0
github.com/containerd/continuity v0.0.0-20210315143101-93e15499afd5 // indirect github.com/containerd/containerd v1.5.0-beta.1 // indirect
github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible
github.com/docker/go-connections v0.4.0 github.com/docker/go-connections v0.4.0 // indirect
github.com/fatedier/frp v0.45.0 github.com/fatedier/frp v0.45.0
github.com/gin-gonic/gin v1.6.3 github.com/gin-gonic/gin v1.6.3
github.com/go-git/go-git/v5 v5.4.2 github.com/go-git/go-git/v5 v5.4.2
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/lithammer/shortuuid v3.0.0+incompatible github.com/lithammer/shortuuid v3.0.0+incompatible
github.com/moby/sys/mount v0.2.0 // indirect
github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf // indirect github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf // indirect
github.com/morikuni/aec v1.0.0 // indirect github.com/morikuni/aec v1.0.0 // indirect
github.com/otiai10/copy v1.6.0 github.com/otiai10/copy v1.6.0
@@ -22,6 +21,7 @@ require (
github.com/urfave/cli/v2 v2.3.0 github.com/urfave/cli/v2 v2.3.0
gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect
gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3 gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3
golang.org/x/crypto v0.16.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
gotest.tools/v3 v3.0.3 // indirect gotest.tools/v3 v3.0.3 // indirect
) )

37
go.sum
View File

@@ -79,8 +79,6 @@ github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3h
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
github.com/Microsoft/hcsshim v0.8.15 h1:Aof83YILRs2Vx3GhHqlvvfyx1asRJKMFIMeVlHsZKtI=
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@@ -155,7 +153,6 @@ github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLE
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102 h1:Qf4HiqfvmB7zS6scsmNgTLmByHbq8n9RTF39v+TzP7A=
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
@@ -174,8 +171,6 @@ github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo=
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
github.com/containerd/continuity v0.0.0-20210315143101-93e15499afd5 h1:k6Dn7shF+i1q4utvCyW4+o9REsCMAeRyORM5IhXMCnw=
github.com/containerd/continuity v0.0.0-20210315143101-93e15499afd5/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
@@ -367,7 +362,6 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@@ -586,9 +580,6 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM=
github.com/moby/sys/mountinfo v0.4.0 h1:1KInV3Huv18akCu58V7lzNlt+jFmqlu1EaErnEHE/VM=
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
@@ -648,7 +639,6 @@ github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5X
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM=
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
@@ -864,7 +854,6 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -889,8 +878,9 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -928,6 +918,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -986,8 +977,10 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1018,8 +1011,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1115,11 +1108,17 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1128,8 +1127,11 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1200,6 +1202,7 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

4
install-binary.bat Normal file
View File

@@ -0,0 +1,4 @@
setx PATH "%PATH%;%cd%"
setx P2PRC "%cd%"
p2p-rendering-computation.exe --dc

8
install-binary.sh Normal file
View File

@@ -0,0 +1,8 @@
# This script setups up the project P2PRC
echo '# Add the following paths to .bashrc or .zshrc based on the configuration you have set'
echo export P2PRC=$PWD
echo export PATH=$PWD:\${PATH}
export P2PRC=${PWD}
export PATH=${PWD}:${PATH}
./p2p-rendering-computation --dc

30
main.go
View File

@@ -1,15 +1,15 @@
package main package main
import ( import (
"log" "log"
"os" "os"
"github.com/Akilan1999/p2p-rendering-computation/cmd" "github.com/Akilan1999/p2p-rendering-computation/cmd"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
// VERSION specifies the version of the platform // VERSION specifies the version of the platform
var VERSION = "1.5.0" var VERSION = "2.0.0"
var mode string var mode string
// Varaibles if mode is client // Varaibles if mode is client
@@ -17,15 +17,15 @@ var OS, Pull_location, Run_script string
var List_servers, Ip_table bool var List_servers, Ip_table bool
func main() { func main() {
app := cli.NewApp() app := cli.NewApp()
app.Name = "p2p-rendering-computation" app.Name = "p2p-rendering-computation"
app.Usage = "p2p cli application to create and access VMs in other servers" app.Usage = "p2p cli application to create and access VMs in other servers"
app.Version = VERSION app.Version = VERSION
app.Flags = cmd.AppConfigFlags app.Flags = cmd.AppConfigFlags
app.Action = cmd.CliAction app.Action = cmd.CliAction
err := app.Run(os.Args) err := app.Run(os.Args)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

View File

@@ -1,13 +1,16 @@
{ {
"ip_address": [ "ip_address": [
{ {
"Name": "Node1", "Name": "Node1",
"IPV4": "64.227.168.102", "IPV4": "139.59.162.154",
"IPV6": "", "IPV6": "",
"Latency": 0, "Latency": 0,
"ServerPort": "8088", "Download": 0,
"NAT": "False", "Upload": 0,
"EscapeImplementation": "None" "ServerPort": "8078",
} "NAT": "False",
] "EscapeImplementation": "",
"CustomInformation": null
}
]
} }

View File

@@ -1,267 +1,294 @@
package p2p package p2p
import ( import (
"encoding/json" "bytes"
"fmt" "crypto/sha256"
"github.com/Akilan1999/p2p-rendering-computation/config" "encoding/json"
"io/ioutil" "fmt"
"net" "github.com/Akilan1999/p2p-rendering-computation/config"
"net/http" "io/ioutil"
"os" "net"
"time" "net/http"
"os"
"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"`
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"`
NAT string `json:"NAT"` BareMetalSSHPort string `json:"BareMetalSSHPort"`
EscapeImplementation string `json:"EscapeImplementation"` NAT string `json:"NAT"`
CustomInformation []byte EscapeImplementation string `json:"EscapeImplementation"`
CustomInformation string `json:"CustomInformation"`
//CustomInformationKey []byte `json:"CustomInformationKey"`
} }
type IP struct { type IP struct {
Query string Query string
} }
// 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 {
return err
}
//
//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-----------"+
// "-----------------\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)
//}
PrettyPrint(table)
if err != nil { return nil
return err
}
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-----------"+
"-----------------\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)
}
//PrettyPrint(table)
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 == "True" && table.IpAddress[i].EscapeImplementation == "None" { if table.IpAddress[i].NAT == "True" && 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) {
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 {
h := sha256.New()
h.Write([]byte(text))
return h.Sum(nil)
}
// ValidateHashSHA256 CustomInformationKey the text and check if the text and
// the hash are the same, if they are
// then return true
// SHA256 is the current hashing algorthm
// used.
func ValidateHashSHA256(text string, Hash []byte) bool {
h := sha256.New()
h.Write([]byte(text))
textHash := h.Sum(nil)
if bytes.Equal(textHash, Hash) {
return true
}
return false
}

View File

@@ -1,202 +1,233 @@
package docker package docker
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"context" "encoding/json"
"encoding/json" "errors"
"errors" "fmt"
"fmt" "github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/config" "github.com/docker/docker/client"
"github.com/docker/docker/api/types" "github.com/google/uuid"
"github.com/docker/docker/api/types/container" "github.com/lithammer/shortuuid"
"github.com/docker/docker/client" "github.com/otiai10/copy"
"github.com/docker/docker/pkg/archive" "github.com/phayes/freeport"
"github.com/docker/go-connections/nat" "io"
"github.com/lithammer/shortuuid" "io/ioutil"
"github.com/phayes/freeport" "os"
"io" "os/exec"
"io/ioutil" "text/template"
"os/exec"
"time"
) )
type DockerVM struct { type DockerVM struct {
SSHUsername string `json:"SSHUsername"` SSHUsername string `json:"SSHUsername"`
SSHPassword string `json:"SSHPassword"` SSHPublcKey string `json:"SSHPublicKey"`
ID string `json:"ID"` ID string `json:"ID"`
TagName string `json:"TagName"` TagName string `json:"TagName"`
ImagePath string `json:"ImagePath"` ImagePath string `json:"ImagePath"`
Ports Ports `json:"Ports"` Ports Ports `json:"Ports"`
GPU string `json:"GPU"` GPU string `json:"GPU"`
TempPath string
BaseImage string
LogsPath string
SSHCommand string `json:"SSHCommand"`
} }
type DockerContainers struct { type DockerContainers struct {
DockerContainer []DockerContainer `json:"DockerContainer"` DockerContainer []DockerContainer `json:"DockerContainer"`
} }
type DockerContainer struct { type DockerContainer struct {
ContainerName string `json:"DockerContainerName"` ContainerName string `json:"DockerContainerName"`
ContainerDescription string `json:"ContainerDescription"` ContainerDescription string `json:"ContainerDescription"`
} }
type Ports struct { type Ports struct {
PortSet []Port `json:"Port"` PortSet []Port `json:"Port"`
} }
type Port struct { type Port struct {
PortName string `json:"PortName"` PortName string `json:"PortName"`
InternalPort int `json:"InternalPort"` InternalPort int `json:"InternalPort"`
Type string `json:"Type"` Type string `json:"Type"`
ExternalPort int `json:"ExternalPort"` ExternalPort int `json:"ExternalPort"`
IsUsed bool `json:"IsUsed"` IsUsed bool `json:"IsUsed"`
Description string `json:"Description"` Description string `json:"Description"`
} }
type ErrorLine struct { type ErrorLine struct {
Error string `json:"error"` Error string `json:"error"`
ErrorDetail ErrorDetail `json:"errorDetail"` ErrorDetail ErrorDetail `json:"errorDetail"`
} }
type ErrorDetail struct { type ErrorDetail struct {
Message string `json:"message"` Message string `json:"message"`
} }
var dockerRegistryUserID = "" var dockerRegistryUserID = ""
// BuildRunContainer Function is incharge to invoke building and running contianer and also allocating external // BuildRunContainer Function is incharge to invoke building and running contianer and also allocating external
// ports // ports
func BuildRunContainer(NumPorts int, GPU string, ContainerName string) (*DockerVM, error) { func BuildRunContainer(NumPorts int, GPU string, ContainerName string, baseImage string, publicKey string) (*DockerVM, error) {
//Docker Struct Variable //Docker Struct Variable
var RespDocker *DockerVM = new(DockerVM) var RespDocker *DockerVM = new(DockerVM)
// Sets if GPU is selected or not // Sets if GPU is selected or not
RespDocker.GPU = GPU RespDocker.GPU = GPU
// Sets Free port to Struct // Get config informatopn
//RespDocker.SSHPort = Ports[0]
//RespDocker.VNCPort = Ports[1]
// Sets appropriate username and password to the
// variables in the struct
RespDocker.SSHUsername = "master"
RespDocker.SSHPassword = "password"
//RespDocker.VNCPassword = "vncpassword"
//Default parameters // Sets Free port to Struct
RespDocker.TagName = "p2p-ubuntu" //RespDocker.SSHPort = Ports[0]
// Get Path from config //RespDocker.VNCPort = Ports[1]
config, err := config.ConfigInit(nil, nil) // Sets appropriate username and password to the
if err != nil { // variables in the struct
return nil, err RespDocker.SSHUsername = "root"
} //RespDocker.BaseImage = "ubuntu:20.04"
RespDocker.ImagePath = config.DefaultDockerFile //RespDocker.VNCPassword = "vncpassword"
// We are checking if the container name is not nil and not equal to the default one used //Default parameters
// which is docker-ubuntu-sshd RespDocker.TagName = "p2p-ubuntu"
if ContainerName != "" && ContainerName != "docker-ubuntu-sshd" { // Get Path from config
Containers, err := ViewAllContainers() config, err := config.ConfigInit(nil, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
RespDocker.ImagePath = config.DefaultDockerFile
RespDocker.LogsPath = config.DockerRunLogs
RespDocker.SSHPublcKey = publicKey
for _, dockerContainer := range Containers.DockerContainer { // We are checking if the container name is not nil and not equal to the default one used
if dockerContainer.ContainerName == ContainerName { // which is docker-ubuntu-sshd
RespDocker.ImagePath = config.DockerContainers + ContainerName + "/" if ContainerName != "" && ContainerName != "docker-ubuntu-sshd" {
RespDocker.TagName = ContainerName Containers, err := ViewAllContainers()
break if err != nil {
} return nil, err
} }
if RespDocker.ImagePath == config.DefaultDockerFile {
return nil, errors.New("Container " + ContainerName + " does not exist in the server")
}
}
PortsInformation, err := OpenPortsFile(RespDocker.ImagePath + "/ports.json") for _, dockerContainer := range Containers.DockerContainer {
if err != nil { if dockerContainer.ContainerName == ContainerName {
return nil, err RespDocker.ImagePath = config.DockerContainers + ContainerName + "/"
} RespDocker.TagName = ContainerName
break
}
}
if RespDocker.ImagePath == config.DefaultDockerFile {
return nil, errors.New("Container " + ContainerName + " does not exist in the server")
}
}
// Number of perts we want to open + number of ports required inside the // Checking if the base image is provided
// docker container if baseImage != "" {
count := NumPorts + len(PortsInformation.PortSet) RespDocker.BaseImage = baseImage
// Creates number of ports } else {
OpenPorts, err := freeport.GetFreePorts(count) RespDocker.BaseImage = "ubuntu:20.04"
if err != nil { }
return nil, err
}
// Allocate external ports to ports available in the ports.json file
for i := range PortsInformation.PortSet {
// Setting external ports
PortsInformation.PortSet[i].ExternalPort = OpenPorts[i]
PortsInformation.PortSet[i].IsUsed = true
}
//Length of Ports allocated from thr port file
portFileLength := len(PortsInformation.PortSet)
// Allocate New ports the user wants to generate
for i := 0; i < NumPorts; i++ {
var TempPort Port
TempPort.PortName = "AutoGen Port"
TempPort.Type = "tcp"
TempPort.InternalPort = OpenPorts[portFileLength+i]
TempPort.ExternalPort = OpenPorts[portFileLength+i]
TempPort.Description = "Auto generated TCP port"
TempPort.IsUsed = false
//Append temp port to port information
PortsInformation.PortSet = append(PortsInformation.PortSet, TempPort)
}
// Setting ports to the docker VM struct
RespDocker.Ports = *PortsInformation
// Gets docker information from env variables // Template docker with the base image provided
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) err = RespDocker.TemplateDockerContainer()
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Builds docker image // Template the DockerFile and point to the temp location
err = RespDocker.imageBuild(cli)
if err != nil {
return nil, err
}
// Runs docker contianer PortsInformation, err := OpenPortsFile(RespDocker.ImagePath + "/" + RespDocker.TagName + "/ports.json")
err = RespDocker.runContainer(cli) if err != nil {
return nil, err
}
if err != nil { // Number of perts we want to open + number of ports required inside the
return nil, err // docker container
} count := NumPorts + len(PortsInformation.PortSet)
// Creates number of ports
OpenPorts, err := freeport.GetFreePorts(count)
if err != nil {
return nil, err
}
// Allocate external ports to ports available in the ports.json file
for i := range PortsInformation.PortSet {
// Setting external ports
PortsInformation.PortSet[i].ExternalPort = OpenPorts[i]
PortsInformation.PortSet[i].IsUsed = true
}
//Length of Ports allocated from thr port file
portFileLength := len(PortsInformation.PortSet)
// Allocate New ports the user wants to generate
for i := 0; i < NumPorts; i++ {
var TempPort Port
TempPort.PortName = "AutoGen Port"
TempPort.Type = "tcp"
TempPort.InternalPort = OpenPorts[portFileLength+i]
TempPort.ExternalPort = OpenPorts[portFileLength+i]
TempPort.Description = "Auto generated TCP port"
TempPort.IsUsed = false
//Append temp port to port information
PortsInformation.PortSet = append(PortsInformation.PortSet, TempPort)
}
// Setting ports to the docker VM struct
RespDocker.Ports = *PortsInformation
return RespDocker, nil // Gets docker information from env variables
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return nil, err
}
// Builds docker image
err = RespDocker.imageBuild(cli)
if err != nil {
return nil, err
}
// Runs docker contianer
err = RespDocker.runContainer(cli)
if err != nil {
return nil, err
}
return RespDocker, nil
} }
// Builds docker image (TODO: relative path for Dockerfile deploy) // Builds docker image (TODO: relative path for Dockerfile deploy)
func (d *DockerVM) imageBuild(dockerClient *client.Client) error { func (d *DockerVM) imageBuild(dockerClient *client.Client) error {
ctx, _ := context.WithTimeout(context.Background(), time.Second*2000) //ctx, _ := context.WithTimeout(context.Background(), time.Second*2000)
//defer cancel() //defer cancel()
tar, err := archive.TarWithOptions(d.ImagePath, &archive.TarOptions{}) var cmd bytes.Buffer
if err != nil { cmd.WriteString("docker build -t " + d.TagName + " " + d.ImagePath + "/" + d.TagName + ` --build-arg SSH_KEY="` + d.SSHPublcKey + `"`)
return err //"-v=/opt/data:/data p2p-ubuntu /start > /dev/null"
} cmdStr := cmd.String()
output, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
fmt.Printf("%s", output)
if err != nil {
return err
}
opts := types.ImageBuildOptions{ //tar, err := archive.TarWithOptions(d.ImagePath+"/"+d.TagName, &archive.TarOptions{})
Dockerfile: "Dockerfile", //if err != nil {
Tags: []string{d.TagName}, // return err
Remove: true, //}
} //
res, err := dockerClient.ImageBuild(ctx, tar, opts) //opts := types.ImageBuildOptions{
if err != nil { // Dockerfile: "Dockerfile",
return err // Tags: []string{d.TagName},
} // Remove: true,
//}
//res, err := dockerClient.ImageBuild(ctx, tar, opts)
//if err != nil {
// return err
//}
//
//defer res.Body.Close()
//
//err = print(res.Body)
//if err != nil {
// return err
//}
defer res.Body.Close() return nil
err = print(res.Body)
if err != nil {
return err
}
return nil
} }
// Starts container and assigns port numbers // Starts container and assigns port numbers
@@ -205,200 +236,273 @@ func (d *DockerVM) imageBuild(dockerClient *client.Client) error {
// -p 3443:6901 -p 3453:22 -p 3434:3434 -p 3245:3245 -v=/opt/data:/data // -p 3443:6901 -p 3453:22 -p 3434:3434 -p 3245:3245 -v=/opt/data:/data
// p2p-ubuntu /start > /dev/null // p2p-ubuntu /start > /dev/null
func (d *DockerVM) runContainer(dockerClient *client.Client) error { func (d *DockerVM) runContainer(dockerClient *client.Client) error {
ctx, _ := context.WithTimeout(context.Background(), time.Second*2000) //ctx, _ := context.WithTimeout(context.Background(), time.Second*2000)
// The first mode runs using the Docker Api. As the API supports using // The first mode runs using the Docker Api. As the API supports using
// CPU and uses a shell script for GPU call because till this point of // CPU and uses a shell script for GPU call because till this point of
// implementation docker api does not support the flag "--gpu all" // implementation docker api does not support the flag "--gpu all"
if d.GPU != "true" { //if d.GPU != "true" {
//Exposed ports for docker config file // //Exposed ports for docker config file
var ExposedPort nat.PortSet // var ExposedPort nat.PortSet
//
// ExposedPort = nat.PortSet{
// "22/tcp": struct{}{},
// //"6901/tcp": struct{}{},
// }
//
// // Port forwarding for VNC and SSH ports
// PortForwarding := nat.PortMap{
// //"22/tcp": []nat.PortBinding{
// // {
// // HostIP: "0.0.0.0",
// // HostPort: fmt.Sprint(d.SSHPort),
// // },
// //},
// //"6901/tcp": []nat.PortBinding{
// // {
// // HostIP: "0.0.0.0",
// // HostPort: fmt.Sprint(d.VNCPort),
// // },
// //},
// }
//
// for i := range d.Ports.PortSet {
// // Parameters "tcp or udp", external port
// Port, err := nat.NewPort(d.Ports.PortSet[i].Type, fmt.Sprint(d.Ports.PortSet[i].InternalPort))
// if err != nil {
// return err
// }
//
// // Exposed Ports
// ExposedPort[Port] = struct{}{}
//
// PortForwarding[Port] = []nat.PortBinding{
// {
// HostIP: "0.0.0.0",
// HostPort: fmt.Sprint(d.Ports.PortSet[i].ExternalPort),
// },
// }
// }
//
// config := &container.Config{
// Image: d.TagName,
// Entrypoint: []string{"/start"},
// Volumes: map[string]struct{}{"/opt/data:/data": {}},
// ExposedPorts: ExposedPort,
// }
// hostConfig := &container.HostConfig{
// PortBindings: PortForwarding,
// }
//
// res, err := dockerClient.ContainerCreate(ctx, config, hostConfig,
// nil, nil, "")
//
// // Set response ID
// d.ID = res.ID
//
// if err != nil {
// return err
// }
//
// err = dockerClient.ContainerStart(ctx, res.ID, types.ContainerStartOptions{})
//
// if err != nil {
// return err
// }
//} else {
// Generate Random ID
id := shortuuid.New()
d.ID = id
ExposedPort = nat.PortSet{ var cmd bytes.Buffer
"22/tcp": struct{}{}, cmd.WriteString("docker run -d=true --name=" + id + " --restart=always ")
//"6901/tcp": struct{}{}, if d.GPU == "true" {
} cmd.WriteString("--gpus all ")
}
// Port forwarding for VNC and SSH ports for i := range d.Ports.PortSet {
PortForwarding := nat.PortMap{ cmd.WriteString("-p " + fmt.Sprint(d.Ports.PortSet[i].ExternalPort) + ":" + fmt.Sprint(d.Ports.PortSet[i].InternalPort) + " ")
//"22/tcp": []nat.PortBinding{ }
// { cmd.WriteString("-v=/tmp:/data " + d.TagName + " > /dev/null")
// HostIP: "0.0.0.0", //"-v=/opt/data:/data p2p-ubuntu /start > /dev/null"
// HostPort: fmt.Sprint(d.SSHPort), cmdStr := cmd.String()
// }, _, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
//}, if err != nil {
//"6901/tcp": []nat.PortBinding{ return err
// { }
// HostIP: "0.0.0.0", //}
// HostPort: fmt.Sprint(d.VNCPort), return nil
// },
//},
}
for i := range d.Ports.PortSet {
// Parameters "tcp or udp", external port
Port, err := nat.NewPort(d.Ports.PortSet[i].Type, fmt.Sprint(d.Ports.PortSet[i].InternalPort))
if err != nil {
return err
}
// Exposed Ports
ExposedPort[Port] = struct{}{}
PortForwarding[Port] = []nat.PortBinding{
{
HostIP: "0.0.0.0",
HostPort: fmt.Sprint(d.Ports.PortSet[i].ExternalPort),
},
}
}
config := &container.Config{
Image: d.TagName,
Entrypoint: []string{"/start"},
Volumes: map[string]struct{}{"/opt/data:/data": {}},
ExposedPorts: ExposedPort,
}
hostConfig := &container.HostConfig{
PortBindings: PortForwarding,
}
res, err := dockerClient.ContainerCreate(ctx, config, hostConfig,
nil, nil, "")
// Set response ID
d.ID = res.ID
if err != nil {
return err
}
err = dockerClient.ContainerStart(ctx, res.ID, types.ContainerStartOptions{})
if err != nil {
return err
}
} else {
// Generate Random ID
id := shortuuid.New()
d.ID = id
var cmd bytes.Buffer
cmd.WriteString("docker run -d=true --name=" + id + " --restart=always --gpus all ")
for i := range d.Ports.PortSet {
cmd.WriteString("-p " + fmt.Sprint(d.Ports.PortSet[i].ExternalPort) + ":" + fmt.Sprint(d.Ports.PortSet[i].InternalPort) + " ")
}
cmd.WriteString("-v=/opt/data:/data " + d.TagName + " /start > /dev/null")
//"-v=/opt/data:/data p2p-ubuntu /start > /dev/null"
cmdStr := cmd.String()
_, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
if err != nil {
return err
}
}
return nil
} }
// StopAndRemoveContainer // StopAndRemoveContainer
// Stop and remove a container // Stop and remove a container
// Reference (https://gist.github.com/frikky/e2efcea6c733ea8d8d015b7fe8a91bf6) // Reference (https://gist.github.com/frikky/e2efcea6c733ea8d8d015b7fe8a91bf6)
func StopAndRemoveContainer(containername string) error { func StopAndRemoveContainer(containername string) error {
ctx := context.Background() //ctx := context.Background()
//
//// Gets docker information from env variables
//client, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
//if err != nil {
// return err
//}
//
//if err = client.ContainerStop(ctx, containername, nil); err != nil {
// return err
//}
//
//removeOptions := types.ContainerRemoveOptions{
// RemoveVolumes: true,
// Force: true,
//}
//
//if err = client.ContainerRemove(ctx, containername, removeOptions); err != nil {
// return err
//}
// Gets docker information from env variables // stop docker container
client, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) var stop bytes.Buffer
if err != nil { stop.WriteString("docker stop " + containername)
return err
}
if err = client.ContainerStop(ctx, containername, nil); err != nil { cmdStr := stop.String()
return err _, err := exec.Command("/bin/sh", "-c", cmdStr).Output()
} if err != nil {
return err
}
removeOptions := types.ContainerRemoveOptions{ // remove docker container
RemoveVolumes: true, var remove bytes.Buffer
Force: true, remove.WriteString("docker remove " + containername)
}
if err = client.ContainerRemove(ctx, containername, removeOptions); err != nil { cmdStr = remove.String()
return err
}
return nil _, err = exec.Command("/bin/sh", "-c", cmdStr).Output()
if err != nil {
return err
}
return nil
} }
// ViewAllContainers returns all containers runnable and which can be built // ViewAllContainers returns all containers runnable and which can be built
func ViewAllContainers() (*DockerContainers, error) { func ViewAllContainers() (*DockerContainers, error) {
// Traverse the deploy path as per given in the config file // Traverse the deploy path as per given in 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
} }
folders, err := ioutil.ReadDir(config.DockerContainers) folders, err := ioutil.ReadDir(config.DockerContainers)
if err != nil { if err != nil {
return nil, err return nil, err
} }
//Declare variable DockerContainers of type struct //Declare variable DockerContainers of type struct
var Containers *DockerContainers = new(DockerContainers) var Containers *DockerContainers = new(DockerContainers)
for _, f := range folders { for _, f := range folders {
if f.IsDir() { if f.IsDir() {
//Declare variable DockerContainer of type struct //Declare variable DockerContainer of type struct
var Container DockerContainer var Container DockerContainer
// Setting container name to deploy name // Setting container name to deploy name
Container.ContainerName = f.Name() Container.ContainerName = f.Name()
// Getting Description from file description.txt // Getting Description from file description.txt
Description, err := ioutil.ReadFile(config.DockerContainers + "/" + Container.ContainerName + "/description.txt") Description, err := ioutil.ReadFile(config.DockerContainers + "/" + Container.ContainerName + "/description.txt")
// 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
} }
// Get Description from description.txt // Get Description from description.txt
Container.ContainerDescription = string(Description) Container.ContainerDescription = string(Description)
Containers.DockerContainer = append(Containers.DockerContainer, Container) Containers.DockerContainer = append(Containers.DockerContainer, Container)
} }
} }
return Containers, nil return Containers, nil
} }
func print(rd io.Reader) error { func print(rd io.Reader) error {
var lastLine string var lastLine string
scanner := bufio.NewScanner(rd) scanner := bufio.NewScanner(rd)
for scanner.Scan() { for scanner.Scan() {
lastLine = scanner.Text() lastLine = scanner.Text()
} }
errLine := &ErrorLine{} errLine := &ErrorLine{}
json.Unmarshal([]byte(lastLine), errLine) json.Unmarshal([]byte(lastLine), errLine)
if errLine.Error != "" { if errLine.Error != "" {
return errors.New(errLine.Error) return errors.New(errLine.Error)
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
return err return err
} }
return nil return nil
} }
func OpenPortsFile(filename string) (*Ports, error) { func OpenPortsFile(filename string) (*Ports, error) {
buf, err := ioutil.ReadFile(filename) buf, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
c := &Ports{} c := &Ports{}
err = json.Unmarshal(buf, c) err = json.Unmarshal(buf, c)
if err != nil { if err != nil {
return nil, fmt.Errorf("in file %q: %v", filename, err) return nil, fmt.Errorf("in file %q: %v", filename, err)
} }
return c, nil return c, nil
}
// TemplateDockerContainer This function templates the docker container
// with the base docker image to use
func (d *DockerVM) TemplateDockerContainer() error {
err := d.CopyToTmpContainer()
if err != nil {
return err
}
// parses the site.yml file in the tmp directory
t, err := template.ParseFiles(d.ImagePath + "/" + d.TagName + "/Dockerfile")
if err != nil {
return err
}
// opens the output file
f, err := os.Create(d.ImagePath + "/" + d.TagName + "/Dockerfile")
if err != nil {
return err
}
image := d.BaseImage
// Pass in Docker Base Image
err = t.Execute(f, image)
if err != nil {
return err
}
return nil
}
// CopyToTmpContainer Creates a copy of the docker folder
func (d *DockerVM) CopyToTmpContainer() error {
// generate rand to UUID this is debug the ansible file if needed
id := uuid.New()
// copies the plugin to the tmp directory
err := copy.Copy(d.ImagePath+"/", d.LogsPath+id.String()+"_"+d.TagName)
if err != nil {
return err
}
// Set the plugin execution to the tmp location
d.TagName = id.String() + "_" + d.TagName
// removing slash
d.ImagePath = d.LogsPath[:len(d.LogsPath)-1]
return nil
} }

View File

@@ -99,7 +99,8 @@ The Docker Containers Dashboard shows key metrics for monitoring running contain
* Container network inbound usage graph * Container network inbound usage graph
* Container network outbound usage graph * Container network outbound usage graph
Note that this dashboard doesn't show the containers that are part of the monitoring stack. > [!NOTE]
> This dashboard doesn't show the containers that are part of the monitoring stack.
***Monitor Services Dashboard*** ***Monitor Services Dashboard***

View File

@@ -14,9 +14,9 @@ To get started on AWS ECS and EC2:
- Copy prometheus.yml configuration present here to base prometheus configuration to enable EC2 service discovery - Copy prometheus.yml configuration present here to base prometheus configuration to enable EC2 service discovery
- `docker compose up -d` - `docker compose up -d`
**Note**: > [!NOTE]
Set query.staleness-delta to 1m make metrics more realtime > Set query.staleness-delta to 1m make metrics more realtime
### TODO ### TODO
- Add alerting rules based on ECS - [ ] Add alerting rules based on ECS

View File

@@ -1,43 +0,0 @@
package server
import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
"net"
"net/rpc"
)
const (
port = "8089"
)
type Listener int
type Docker struct {
docker *docker.DockerVM
}
// Starts container using RPC calls
func (l *Listener) StartContainer(reply *Docker) error {
vm, err := docker.BuildRunContainer(3, "false", "")
if err != nil {
return err
}
fmt.Printf("Receive: %v\n", vm)
*reply = Docker{vm}
return nil
}
func Rpc() {
rpcServer, err := net.ResolveTCPAddr("tcp", "0.0.0.0:"+port)
if err != nil {
fmt.Print(err)
}
inbound, err := net.ListenTCP("tcp", rpcServer)
if err != nil {
fmt.Print(err)
}
listener := new(Listener)
rpc.Register(listener)
rpc.Accept(inbound)
}

View File

@@ -1,226 +1,333 @@
package server package server
import ( import (
"encoding/json" b64 "encoding/base64"
"fmt" "encoding/json"
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable" "fmt"
"github.com/Akilan1999/p2p-rendering-computation/config" "github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
"github.com/Akilan1999/p2p-rendering-computation/p2p" "github.com/Akilan1999/p2p-rendering-computation/config"
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp" "github.com/Akilan1999/p2p-rendering-computation/p2p"
"github.com/Akilan1999/p2p-rendering-computation/server/docker" "github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
"github.com/gin-gonic/gin" "github.com/Akilan1999/p2p-rendering-computation/server/docker"
"io/ioutil" "github.com/gin-gonic/gin"
"net/http" "io/ioutil"
"strconv" "net/http"
"time" "strconv"
"time"
) )
func Server() (*gin.Engine, error) { func Server() (*gin.Engine, error) {
r := gin.Default() r := gin.Default()
//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", "")
var PortsInt int BaseImage := c.DefaultQuery("BaseImage", "")
PublicKey := c.DefaultQuery("PublicKey", "")
var PortsInt int
// Convert Get Request value to int if PublicKey == "" {
fmt.Sscanf(Ports, "%d", &PortsInt) c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", "Publickey not passed"))
}
// Creates container and returns-back result to PublicKeyDecoded, err := b64.StdEncoding.DecodeString(PublicKey)
// access container if err != nil {
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName) c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
if err != nil { // Convert Get Request value to int
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err)) fmt.Sscanf(Ports, "%d", &PortsInt)
}
// Ensures that FRP is triggered only if a proxy address is provided fmt.Println(string(PublicKeyDecoded[:]))
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))
}
fmt.Println(resp)
}
c.JSON(http.StatusOK, resp) // Creates container and returns-back result to
}) // access container
resp, err := docker.BuildRunContainer(PortsInt, GPU, ContainerName, BaseImage, string(PublicKeyDecoded[:]))
//Remove container if err != nil {
r.GET("/RemoveContainer", func(c *gin.Context) { c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
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 // Ensures that FRP is triggered only if a proxy address is provided
r.GET("/ShowImages", func(c *gin.Context) { if ProxyIpAddr.Ipv4 != "" && c.Request.Host != "localhost:"+config.ServerPort && c.Request.Host != "0.0.0.0:"+config.ServerPort {
resp, err := docker.ViewAllContainers() resp, err = frp.StartFRPCDockerContainer(ProxyIpAddr.Ipv4, lowestLatencyIpAddress.ServerPort, resp)
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.JSON(http.StatusOK, resp)
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)) //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")
})
// If there is a proxy port specified //Show images available
// then starts the FRP server r.GET("/ShowImages", func(c *gin.Context) {
//if config.FRPServerPort != "0" { resp, err := docker.ViewAllContainers()
// go frp.StartFRPProxyFromRandom() if err != nil {
//} c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
}
c.JSON(http.StatusOK, resp)
})
// TODO check if IPV6 or Proxy port is specified // Request for port no from Server with address
// if not update current entry as proxy address r.GET("/FRPPort", func(c *gin.Context) {
// with appropriate port on IP Table port, err := frp.StartFRPProxyFromRandom()
if config.BehindNAT == "True" { if err != nil {
table, err := p2p.ReadIpTable() c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
if err != nil { }
return nil, err
}
var lowestLatency int64 c.String(http.StatusOK, strconv.Itoa(port))
// random large number })
lowestLatency = 10000000
for i, _ := range table.IpAddress { r.GET("/MAPPort", func(c *gin.Context) {
// Checks if the ping is the lowest and if the following node is acting as a proxy Ports := c.DefaultQuery("port", "0")
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" { url, _, err := MapPort(Ports)
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency { if err != nil {
lowestLatency = table.IpAddress[i].Latency.Milliseconds() c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
lowestLatencyIpAddress = table.IpAddress[i] }
}
}
// If there is an identified node c.String(http.StatusOK, url)
if lowestLatency != 10000000 { })
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil {
return nil, err
}
// 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
}
// updating with the current proxy address // If there is a proxy port specified
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4 // then starts the FRP server
ProxyIpAddr.ServerPort = proxyPort //if config.FRPServerPort != "0" {
ProxyIpAddr.Name = config.MachineName // go frp.StartFRPProxyFromRandom()
ProxyIpAddr.NAT = "False" //}
ProxyIpAddr.EscapeImplementation = "FRP"
// append the following to the ip table // TODO check if IPV6 or Proxy port is specified
table.IpAddress = append(table.IpAddress, ProxyIpAddr) // if not update current entry as proxy address
// write information back to the IP Table // with appropriate port on IP Table
table.WriteIpTable() if config.BehindNAT == "True" {
// update ip table // Remove nodes currently not pingable
go clientIPTable.UpdateIpTableListClient() clientIPTable.RemoveOfflineNodes()
}
} table, err := p2p.ReadIpTable()
if err != nil {
return nil, err
}
// Run gin server on the specified port var lowestLatency int64
go r.Run(":" + config.ServerPort) // random large number
lowestLatency = 10000000
return r, nil 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 != "" {
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].NAT != "" {
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
lowestLatencyIpAddress = table.IpAddress[i]
}
}
// If there is an identified node
if lowestLatency != 10000000 {
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil {
return nil, err
}
// 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
}
// updating with the current proxy address
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
ProxyIpAddr.ServerPort = proxyPort
ProxyIpAddr.Name = config.MachineName
ProxyIpAddr.NAT = "False"
ProxyIpAddr.EscapeImplementation = "FRP"
// Sorry Jan it's a string
// Yes I could convert it
// to a boolean operator
// But I am way too tired
if config.BareMetal == "True" {
_, SSHPort, err := MapPort("22")
if err != nil {
return nil, err
}
ProxyIpAddr.BareMetalSSHPort = SSHPort
}
//ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey)
// append the following to the ip table
table.IpAddress = append(table.IpAddress, ProxyIpAddr)
// write information back to the IP Table
err = table.WriteIpTable()
if err != nil {
return nil, err
}
// update ip table
go func() error {
err := clientIPTable.UpdateIpTableListClient()
if err != nil {
fmt.Println(err)
return err
}
return nil
}()
}
}
// Run gin server on the specified port
go r.Run(":" + config.ServerPort)
return r, nil
}
func MapPort(port string) (string, string, error) {
//Get Server port based on the config file
config, err := config.ConfigInit(nil, nil)
if err != nil {
return "", "", err
}
// update IPTable with new port and ip address and update ip table
var ProxyIpAddr p2p.IpAddress
var lowestLatencyIpAddress p2p.IpAddress
clientIPTable.RemoveOfflineNodes()
table, err := p2p.ReadIpTable()
if err != nil {
return "", "", err
}
var lowestLatency int64
// random large number
lowestLatency = 10000000
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 != "" {
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].NAT != "" {
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
lowestLatencyIpAddress = table.IpAddress[i]
}
}
// If there is an identified node
if lowestLatency != 10000000 {
serverPort, err := frp.GetFRPServerPort("http://" + lowestLatencyIpAddress.Ipv4 + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil {
return "", "", err
}
// 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, port, "")
if err != nil {
return "", "", err
}
// updating with the current proxy address
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
ProxyIpAddr.ServerPort = proxyPort
ProxyIpAddr.Name = config.MachineName
ProxyIpAddr.NAT = "False"
ProxyIpAddr.EscapeImplementation = "FRP"
//ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey)
}
return ProxyIpAddr.Ipv4 + ":" + ProxyIpAddr.ServerPort, ProxyIpAddr.ServerPort, nil
} }