108 Commits

Author SHA1 Message Date
36930be8e4 added write config support 2025-06-28 12:03:56 +01:00
be1f3308ca Merge branch 'master' of github.com:Akilan1999/p2p-rendering-computation 2025-06-07 14:07:53 +01:00
b3fcc10cd8 fixed p2prc docs 2025-06-07 14:06:55 +01:00
Akilan Selvacoumar
301a87e758 Update README.md 2025-06-06 20:43:47 +01:00
c9f4c8b5c7 added p2prc haskell logo 2025-06-06 17:00:19 +01:00
10b3c6bae3 fixed folder copied inside 2025-06-06 16:16:46 +01:00
d4e73e9d34 added manual installation documentation 2025-06-06 15:59:37 +01:00
4c7deb948f added haskell build instruction 2025-06-06 15:43:48 +01:00
54a675e0c0 changed command line argument for testing 2025-06-06 14:24:26 +01:00
3c3cfac5e2 fixed pass through custom information 2025-06-04 15:51:07 +01:00
6a24da74ef removed index.org~ from main directory 2025-06-03 15:22:05 +01:00
0fe1b0c622 fixed incorrect documentation use 2025-06-03 15:09:45 +01:00
7d3fc9b25f added generated docs html 2025-06-03 15:02:14 +01:00
Akilan Selvacoumar
6281b0f532 Merge pull request #128 from xecarlox94/nix
Nix template addition
2025-06-03 14:46:16 +01:00
1711b01979 finished documentation 2025-06-02 23:59:23 +01:00
438b4d0424 fixed coding bugs, refined text 2025-06-02 21:05:22 +01:00
22c5d61082 finished mvp for nix templating 2025-06-02 00:43:50 +01:00
a1bf13cac3 finishing automated setup 2025-06-02 00:37:28 +01:00
616bf76bda finishing automated setup 2025-06-02 00:31:29 +01:00
539bceee7d finishing automated setup 2025-06-02 00:31:04 +01:00
69b9ea3527 finishing automated setup 2025-06-02 00:11:59 +01:00
27f4615cd1 finishing automated setup 2025-06-02 00:07:53 +01:00
01e19d9a8c adding git actions 2025-06-02 00:03:24 +01:00
aafc0ebdd7 adding git actions 2025-06-01 23:54:25 +01:00
9de0b1b985 adding git actions 2025-06-01 23:52:00 +01:00
4c12d74789 adding git actions 2025-06-01 23:50:41 +01:00
f06df58a8a adding git actions 2025-06-01 23:47:11 +01:00
30004d59c6 adding git actions 2025-06-01 23:44:57 +01:00
4c8cde8857 adding git actions 2025-06-01 23:34:01 +01:00
994c52faf0 adding git actions 2025-06-01 23:25:41 +01:00
5e65381377 adding git actions 2025-06-01 20:57:38 +01:00
ff66d55153 adding git actions 2025-06-01 20:54:38 +01:00
50983dbb19 adding git actions 2025-06-01 20:50:49 +01:00
189edd73b1 adding git actions 2025-06-01 20:48:59 +01:00
27670f2408 adding git actions 2025-06-01 19:55:00 +01:00
b301a54fba adding git actions 2025-06-01 19:53:33 +01:00
05e29aab0d adding git actions 2025-06-01 19:47:17 +01:00
b883feb825 adding git actions 2025-06-01 19:44:43 +01:00
5059444d26 adding git actions 2025-06-01 19:42:23 +01:00
be3be96987 adding git actions 2025-06-01 19:39:32 +01:00
682424074f adding git actions 2025-06-01 19:36:41 +01:00
9d0ec3eba4 adding git actions 2025-06-01 19:34:32 +01:00
bf87217b9a adding git actions 2025-06-01 19:27:52 +01:00
e4638232d3 adding git actions 2025-06-01 19:24:56 +01:00
fb6c3ab091 adding new version for p2prc-hs bootstrapping 2025-06-01 15:12:16 +01:00
a59657a93b removing wasm file 2025-05-31 15:18:27 +01:00
30ea1f810a Merge remote-tracking branch 'refs/remotes/principal/master' 2025-05-31 11:11:00 +01:00
fe72625266 removed erroneous commands 2025-05-31 10:44:10 +01:00
d2030b7d74 updating lock versions 2025-05-31 00:17:59 +01:00
73a283a545 another attempt to test bootstrapping 2025-05-31 00:07:50 +01:00
623cfffb6a another attempt to test bootstrapping 2025-05-31 00:05:04 +01:00
3669fdfad2 adding initHaskellProject to bootstrap project 2025-05-30 23:56:03 +01:00
f39fab04ce adding initHaskellProject to bootstrap project 2025-05-30 23:41:34 +01:00
12ff0ceb37 adding initHaskellProject to bootstrap project 2025-05-30 23:36:27 +01:00
99c62a8dca adding initHaskellProject to bootstrap project 2025-05-30 23:32:49 +01:00
ce5c80a10e adding initHaskellProject to bootstrap project 2025-05-30 23:31:40 +01:00
46ef4e1db9 adding initHaskellProject to bootstrap project 2025-05-30 23:29:28 +01:00
14743f7f9b adding initHaskellProject to bootstrap project 2025-05-30 23:27:10 +01:00
a461c2da64 adding initHaskellProject to bootstrap project 2025-05-30 23:02:06 +01:00
99c9c41528 Documentation for Simulation added 2025-05-30 18:06:32 +01:00
0e260cf8e4 Made simulation simple 2025-05-30 17:10:54 +01:00
02e58493f5 added working version of simulator 2025-05-30 17:09:36 +01:00
a46ec3575c Simulation base code 2025-05-30 16:23:39 +01:00
2d55643dd9 removed heavy WASM binary 2025-05-30 11:59:32 +01:00
1ac0647d46 refactoring nix flake template 2025-05-30 00:04:43 +01:00
a07a412c72 temporary fix to test remote flake init 2025-05-29 23:52:14 +01:00
e04e918328 fixed haskell template 2025-05-29 23:36:11 +01:00
0bb949a1e2 fixed overlay and templates 2025-05-29 23:34:08 +01:00
cf6611087a adding haskell template providing dev/prod environments 2025-05-29 23:29:55 +01:00
b1a69189d3 adding haskell template providing dev/prod environments 2025-05-29 23:20:21 +01:00
ad76773111 adding haskell template providing dev/prod environments 2025-05-29 23:13:11 +01:00
ec46f74c4e adding haskell template providing dev/prod environments 2025-05-29 23:10:12 +01:00
3fb225676f fixed devshell environment 2025-05-29 00:23:42 +01:00
0e86459122 fixed p2prc-hs issue 2025-05-28 22:25:09 +01:00
77ebb76838 updating flake 2025-05-28 00:04:49 +01:00
85806ab035 refactoring flake code 2025-05-27 23:49:08 +01:00
9d92ecb202 working on template for haskell 2025-05-27 23:22:47 +01:00
5fa625160e improving overlays 2025-05-26 21:26:40 +01:00
403ad72ddb fixing environment 2025-05-26 21:08:11 +01:00
6446681719 renaming overlay file 2025-05-26 01:16:03 +01:00
d50534e270 improving executable exposure 2025-05-26 01:06:42 +01:00
8a2dfb7b5b fixed haskell development environment 2025-05-26 00:15:36 +01:00
0f4f52cb8b working on haskell development shell 2025-05-26 00:06:11 +01:00
cd8bb2df8c removed redundant code from flake 2025-05-25 23:45:44 +01:00
fa5b7a27d5 fixed overlays typo 2025-05-25 23:17:03 +01:00
21f0fc79c1 removed executable from haskell project 2025-05-25 22:07:26 +01:00
bebe2a02a0 improving nix flake for haskell library bootstrapping 2025-05-25 19:09:41 +01:00
7b0b2404b2 improving overlay 2025-05-24 17:59:16 +01:00
724daf5eda preparing overlays for build system 2025-05-24 16:58:08 +01:00
c262e612e1 preparing overlays for build system 2025-05-24 16:53:01 +01:00
257d91a432 fixing nix development and build environments 2025-05-21 23:11:56 +01:00
42cf9bd028 fixing nix env 2025-05-20 23:51:33 +01:00
7c34c5385a fix abstraction 2025-05-17 23:30:58 +01:00
d79c28c32f added kill docs script 2025-04-28 23:22:22 +01:00
Akilan Selvacoumar
7b0d36873b Merge pull request #127 from Akilan1999/add-root-node
Added feature to add root node
2025-04-28 23:17:49 +01:00
2283736cc6 added language bindings, python implementation and docs for the feature add
root node
2025-04-28 23:15:35 +01:00
51b253df15 added feature to add root node 2025-04-28 22:22:29 +01:00
b9f5dec9de added static server 2025-04-25 23:53:00 +01:00
30b464449c added basic static server 2025-04-25 23:50:56 +01:00
ffd711f448 added run docs server locally 2025-04-25 23:40:18 +01:00
0d01d70c2b renamed docs directory 2025-04-25 23:22:39 +01:00
6b1edd3d8a revert back docs directory 2025-04-25 23:18:19 +01:00
5cf1e144aa moved docs to root folder 2025-04-25 23:07:24 +01:00
Akilan Selvacoumar
f605e2e06b Merge pull request #126 from Akilan1999/simulation
Haskell and Documentation fixes
2025-04-25 22:31:32 +01:00
873caa911c modified docs 2025-04-25 22:27:39 +01:00
73a470e201 comment out config behavoir since only used for prints 2025-04-25 21:23:42 +01:00
805514edfa uniform variable naming haskell 2025-04-25 20:56:54 +01:00
Akilan Selvacoumar
5e3a4e8b7a Merge pull request #125 from Akilan1999/python-addcustom-information
Python addcustom information
2025-04-25 13:05:38 +01:00
53 changed files with 2582 additions and 1645 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1,49 +0,0 @@
name: Deploy Jekyll with GitHub Pages dependencies preinstalled
on:
# Runs on pushes targeting the default branch
push:
branches: ["main", "master"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow one concurrent deployment
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
# Build job
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Pages
uses: actions/configure-pages@v2
- name: Build with Jekyll
uses: actions/jekyll-build-pages@v1
with:
source: ./
destination: ./_site
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1

1
.gitignore vendored
View File

@@ -31,6 +31,7 @@ server/docker/containers/
# generic folder to ignore # generic folder to ignore
export/ export/
exports/
# Any testing file # Any testing file
*test *test

View File

@@ -2,11 +2,11 @@ package main
import "C" import "C"
import ( import (
"encoding/json" "encoding/json"
"time" "time"
"github.com/Akilan1999/p2p-rendering-computation/abstractions" "github.com/Akilan1999/p2p-rendering-computation/abstractions"
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp" "github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
) )
// The Client package where data-types // The Client package where data-types
@@ -18,20 +18,20 @@ import (
//export StartContainer //export StartContainer
func StartContainer(IP string) (output *C.char) { func StartContainer(IP string) (output *C.char) {
container, err := abstractions.StartContainer(IP) container, err := abstractions.StartContainer(IP)
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
return ConvertStructToJSONString(container) return ConvertStructToJSONString(container)
} }
//export RemoveContainer //export RemoveContainer
func RemoveContainer(IP string, ID string) (output *C.char) { func RemoveContainer(IP string, ID string) (output *C.char) {
err := abstractions.RemoveContainer(IP, ID) err := abstractions.RemoveContainer(IP, ID)
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
return C.CString("Success") return C.CString("Success")
} }
// --------------------------------- Plugin Control ---------------------------------------- // --------------------------------- Plugin Control ----------------------------------------
@@ -77,20 +77,20 @@ func RemoveContainer(IP string, ID string) (output *C.char) {
//export GetSpecs //export GetSpecs
func GetSpecs(IP string) (output *C.char) { func GetSpecs(IP string) (output *C.char) {
specs, err := abstractions.GetSpecs(IP) specs, err := abstractions.GetSpecs(IP)
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
return ConvertStructToJSONString(specs) return ConvertStructToJSONString(specs)
} }
//export Init //export Init
func Init(customConfig string) (output *C.char) { func Init(customConfig string) (output *C.char) {
init, err := abstractions.Init(customConfig) init, err := abstractions.Init(customConfig)
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
return ConvertStructToJSONString(init) return ConvertStructToJSONString(init)
} }
@@ -98,81 +98,90 @@ func Init(customConfig string) (output *C.char) {
//export ViewIPTable //export ViewIPTable
func ViewIPTable() (output *C.char) { func ViewIPTable() (output *C.char) {
table, err := abstractions.ViewIPTable() table, err := abstractions.ViewIPTable()
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
return ConvertStructToJSONString(table) return ConvertStructToJSONString(table)
} }
//export UpdateIPTable //export UpdateIPTable
func UpdateIPTable() (output *C.char) { func UpdateIPTable() (output *C.char) {
err := abstractions.UpdateIPTable() err := abstractions.UpdateIPTable()
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
return C.CString("Success") return C.CString("Success")
} }
//export EscapeFirewall //export EscapeFirewall
func EscapeFirewall(HostOutsideNATIP string, HostOutsideNATPort string, internalPort string) (output *C.char) { func EscapeFirewall(HostOutsideNATIP string, HostOutsideNATPort string, internalPort string) (output *C.char) {
// Get free port from P2PRC server node // Get free port from P2PRC server node
serverPort, err := frp.GetFRPServerPort("http://" + HostOutsideNATIP + ":" + HostOutsideNATPort) serverPort, err := frp.GetFRPServerPort("http://" + HostOutsideNATIP + ":" + HostOutsideNATPort)
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
ExposedPort, err := frp.StartFRPClientForServer(HostOutsideNATIP+":"+HostOutsideNATPort, serverPort, internalPort, "") ExposedPort, err := frp.StartFRPClientForServer(HostOutsideNATIP+":"+HostOutsideNATPort, serverPort, internalPort, "")
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
return C.CString(ExposedPort) return C.CString(ExposedPort)
} }
//export MapPort //export MapPort
func MapPort(Port string, DomainName string, ServerAddress string) *C.char { func MapPort(Port string, DomainName string, ServerAddress string) *C.char {
Address, err := abstractions.MapPort(Port, DomainName, ServerAddress) Address, err := abstractions.MapPort(Port, DomainName, ServerAddress)
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
return C.CString(Address.EntireAddress) return C.CString(Address.EntireAddress)
} }
//export CustomInformation //export CustomInformation
func CustomInformation(CustomInformation string) *C.char { func CustomInformation(CustomInformation string) *C.char {
err := abstractions.AddCustomInformation(CustomInformation) err := abstractions.AddCustomInformation(CustomInformation)
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
return C.CString("Success") return C.CString("Success")
}
//export AddRootNode
func AddRootNode(IP string, Port string) *C.char {
err := abstractions.AddRootNode(IP, Port)
if err != nil {
return C.CString(err.Error())
}
return C.CString("Success")
} }
// --------------------------------- Controlling Server ---------------------------------------- // --------------------------------- Controlling Server ----------------------------------------
//export Server //export Server
func Server() (output *C.char) { func Server() (output *C.char) {
_, err := abstractions.Start() _, err := abstractions.Start()
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
return ConvertStructToJSONString("") return ConvertStructToJSONString("")
} }
// --------------------------------- Helper Functions ---------------------------------------- // --------------------------------- Helper Functions ----------------------------------------
func ConvertStructToJSONString(Struct interface{}) *C.char { func ConvertStructToJSONString(Struct interface{}) *C.char {
jsonBytes, err := json.Marshal(Struct) jsonBytes, err := json.Marshal(Struct)
if err != nil { if err != nil {
return C.CString(err.Error()) return C.CString(err.Error())
} }
// Convert the JSON bytes to a string // Convert the JSON bytes to a string
return C.CString(string(jsonBytes)) return C.CString(string(jsonBytes))
} }
func main() {} func main() {}

View File

@@ -15,7 +15,6 @@
|--------------|-----------------------------------------| |--------------|-----------------------------------------|
| Copyright | Copyright (C) 2006-2024 John MacFarlane | | Copyright | Copyright (C) 2006-2024 John MacFarlane |
| License | GNU GPL, version 2 or above | | License | GNU GPL, version 2 or above |
| Maintainer | John MacFarlane \<jgm@berkeley.edu\> |
| Stability | alpha | | Stability | alpha |
| Portability | portable | | Portability | portable |
| Safe Haskell | Safe-Inferred | | Safe Haskell | Safe-Inferred |

View File

@@ -1,4 +0,0 @@
module Paths_p2prc where
import Data.Version
version :: Version; version = makeVersion [0,1,0,0]
getDataDir :: IO FilePath; getDataDir = return "/Users/akilan/.mcabal/mhs-0.12.3.0/packages/p2prc-0.1.0.0/data"

View File

@@ -18,23 +18,41 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gomod2nix": { "gomod2nix": {
"inputs": { "inputs": {
"flake-utils": [ "flake-utils": [
"p2prc", "p2prc-main",
"flake-utils" "flake-utils"
], ],
"nixpkgs": [ "nixpkgs": [
"p2prc", "p2prc-main",
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1733668782, "lastModified": 1745875161,
"narHash": "sha256-tPsqU00FhgdFr0JiQUiBMgPVbl1jbPCY5gbFiJycL3I=", "narHash": "sha256-0YkWCS13jpoo3+sX/3kcgdxBNt1VZTmvF+FhZb4rFKI=",
"owner": "nix-community", "owner": "nix-community",
"repo": "gomod2nix", "repo": "gomod2nix",
"rev": "514283ec89c39ad0079ff2f3b1437404e4cba608", "rev": "2cbd7fdd6eeab65c494cc426e18f4e4d2a5e35c0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -57,11 +75,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1735834308, "lastModified": 1748026106,
"narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", "narHash": "sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6df24922a1400241dae323af55f30e4318a6ca65", "rev": "063f43f2dbdef86376cc29ad646c45c46e93234c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -71,28 +89,28 @@
"type": "github" "type": "github"
} }
}, },
"p2prc": { "p2prc-main": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils_2",
"gomod2nix": "gomod2nix", "gomod2nix": "gomod2nix",
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
"lastModified": 0, "lastModified": 0,
"narHash": "sha256-f4e4JcQzBS+R+8HqJbQVeecInm2ggInJuSSymj6gtQo=", "narHash": "sha256-5qbaxawuLsg8iu9076zlAbLtTFSNJaTz7WERS5rWRxU=",
"path": "/nix/store/hmk8v0lxifsscll054qsdnzxqfql1998-source", "path": "/nix/store/lg694r23fzc6v5ai3qqcszq1fp44djg2-source",
"type": "path" "type": "path"
}, },
"original": { "original": {
"path": "/nix/store/hmk8v0lxifsscll054qsdnzxqfql1998-source", "path": "/nix/store/lg694r23fzc6v5ai3qqcszq1fp44djg2-source",
"type": "path" "type": "path"
} }
}, },
"root": { "root": {
"inputs": { "inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"p2prc": "p2prc", "p2prc-main": "p2prc-main"
"utils": "utils"
} }
}, },
"systems": { "systems": {
@@ -124,24 +142,6 @@
"repo": "default", "repo": "default",
"type": "github" "type": "github"
} }
},
"utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View File

@@ -1,24 +1,28 @@
{ {
description = "Nix flake for P2PRC Haskell library"; description = "Nix flake for P2PRC Haskell library";
inputs = { inputs = {
p2prc.url = "../../"; flake-utils.url = "github:numtide/flake-utils";
utils.url = "github:numtide/flake-utils"; p2prc-main.url = "../../";
}; };
outputs = { self, nixpkgs, utils, p2prc }: utils.lib.eachDefaultSystem (system: outputs = { nixpkgs, flake-utils, p2prc-main, ... }:
let flake-utils.lib.eachDefaultSystem (system:
pkgs = nixpkgs.legacyPackages.${system}; let
in pkgs = nixpkgs.legacyPackages.${system};
{ in
devShell = pkgs.mkShell { {
buildInputs = with pkgs; [
cabal-install packages.default = pkgs.haskellPackages.callPackage ./project.nix {};
haskell.compiler.ghc96
zlib.dev devShell = pkgs.mkShell {
p2prc.outputs.packages.${system}.default buildInputs = with pkgs; [
]; cabal2nix
}; cabal-install
} ghc
); zlib.dev
p2prc-main.packages.${system}.default
];
};
}
);
} }

View File

@@ -3,6 +3,7 @@ module API
( P2PRCapi(..) ( P2PRCapi(..)
, MapPortRequest(..) , MapPortRequest(..)
, p2prcAPI , p2prcAPI
, P2PRCommands(..)
) )
where where
@@ -13,6 +14,7 @@ import System.Process ( ProcessHandle )
import Data.Aeson ( FromJSON ) import Data.Aeson ( FromJSON )
import Error import Error
( IOEitherError ( IOEitherError
) )
@@ -20,19 +22,21 @@ import Error
import JSON import JSON
( IPAddressTable(..) ( IPAddressTable(..)
, MapPortResponse(..) , MapPortResponse(..)
, P2prcConfig , P2PRCConfig
) )
import CLI import CLI
( StdInput(..) ( StdInput(..)
, CLIOpt(..) , CLIOpt(..)
, eitherErrDecode , eitherErrDecode
, p2PrcCmdName , p2prcCmdName
, eitherExecProcess , eitherExecProcess
, eitherExecProcessParser , eitherExecProcessParser
, spawnProcP2Prc , spawnProcP2PRC
) )
-- import System.Environment (lookupEnv)
-- | Lower level P2PRC Haskell api that exposes basic functionality necessary to joint the network. -- | Lower level P2PRC Haskell api that exposes basic functionality necessary to joint the network.
@@ -41,21 +45,32 @@ data P2PRCapi
= MkP2PRCapi = MkP2PRCapi
{ startServer :: IOEitherError ProcessHandle { startServer :: IOEitherError ProcessHandle
-- ^ Start server -- ^ Start server
, execInitConfig :: IOEitherError P2prcConfig -- , execInitConfig :: IOEitherError P2PRCConfig
-- ^ Instantiate server configuration -- ^ Instantiate server configuration
, execListServers :: IOEitherError IPAddressTable , execListServers :: IOEitherError IPAddressTable
-- ^ List servers in network -- ^ List servers in network
, execMapPort :: MapPortRequest -> IOEitherError MapPortResponse , execMapPort :: MapPortRequest -> IOEitherError MapPortResponse
-- ^ Exposes and associates a local TCP port with a remote DNS address -- ^ Exposes and associates a local TCP port with a remote DNS address
, execMaybeMapPortAndAddCustomInformation :: Maybe MapPortRequest -> PassCustomInformation -> IOEitherError String
, execAddCustomInformation :: PassCustomInformation -> IOEitherError String
} }
-- | This defines the request required to create an association between a TCP socket port and a DNS server in the network. If successful, it makes a resource available in the network. -- | This defines the request required to create an association between a TCP socket port and a DNS server in the network. If successful, it makes a resource available in the network.
data MapPortRequest = data MapPortRequest =
MkMapPortRequest -- ^ P2PRC's port allocation request value MkMapPortRequest -- ^ P2PRC's port allocation request value
Int -- ^ TCP socket number Int -- ^ TCP socket number
String -- ^ Network domain name String -- ^ Network domain name
-- | This defined the custom information required to be passed through.
newtype PassCustomInformation =
MkAddCustomInformation
String
data P2PRCommands
= MapPort MapPortRequest
| CustomInformation PassCustomInformation
{-| {-|
This function intiates a pure P2PRC runtime state and builds up a 'P2PRCapi' API instance. It allows a developer to create computing orchestration algorithms using the API primitives. This function intiates a pure P2PRC runtime state and builds up a 'P2PRCapi' API instance. It allows a developer to create computing orchestration algorithms using the API primitives.
@@ -92,16 +107,22 @@ main =
{-# WARNING p2prcAPI "This function is currently unstable because the configuration reading is dependent on the following issue: https://github.com/Akilan1999/p2p-rendering-computation/issues/120" #-} {-# WARNING p2prcAPI "This function is currently unstable because the configuration reading is dependent on the following issue: https://github.com/Akilan1999/p2p-rendering-computation/issues/120" #-}
p2prcAPI :: P2PRCapi p2prcAPI :: P2PRCapi
p2prcAPI = p2prcAPI = let
execTemp :: Maybe MapPortRequest -> PassCustomInformation -> IOEitherError String
execTemp mp ci = undefined
in
MkP2PRCapi MkP2PRCapi
{ startServer = spawnProcP2Prc p2PrcCmdName [ MkOptAtomic "--s" ] { startServer = spawnProcP2PRC p2prcCmdName [ MkOptAtomic "-s" ]
, execListServers = , execListServers =
execProcP2PrcParser [ MkOptAtomic "--ls" ] MkEmptyStdInput execProcP2PRCParser [ MkOptAtomic "--ls" ] MkEmptyStdInput
, execMapPort = , execMapPort =
\ (MkMapPortRequest portNumber domainName) -> \ (MkMapPortRequest portNumber domainName) ->
execProcP2PrcParser execProcP2PRCParser
[ MkOptTuple [ MkOptTuple
( "--mp" ( "--mp"
, show portNumber , show portNumber
@@ -113,39 +134,44 @@ p2prcAPI =
] ]
MkEmptyStdInput MkEmptyStdInput
, execInitConfig = do , execMaybeMapPortAndAddCustomInformation = execTemp
, execAddCustomInformation = execTemp Nothing
confInitRes <- execProcP2Prc [ MkOptAtomic "--dc" ] MkEmptyStdInput -- , execInitConfig = do
case confInitRes of -- confInitRes <- execProcP2PRC [ MkOptAtomic "--dc" ] MkEmptyStdInput
(Right _) -> do
-- TODO: get config file name dynamically -- case confInitRes of
-- -- (Right _) -> do
currDirectory <- getCurrentDirectory
-- TODO: change values before loading file -- maybeValue <- lookupEnv "P2PRC"
let fname = currDirectory ++ "/config.json" :: FilePath
-- -- TODO: get config file name dynamically
-- --
-- currDirectory <- getCurrentDirectory
-- -- TODO: change values before loading file
-- let fname = currDirectory ++ "/config.json" :: FilePath
-- TODO: read config check if file exists -- -- TODO: read config check if file exists
configContent <- readFile fname -- configContent <- readFile fname
pure $ eitherErrDecode configContent -- pure $ eitherErrDecode configContent
(Left err) -> pure $ Left err -- (Left err) -> pure $ Left err
} }
where where
execProcP2PrcParser :: execProcP2PRCParser ::
FromJSON a => FromJSON a =>
[CLIOpt] -> StdInput -> IOEitherError a [CLIOpt] -> StdInput -> IOEitherError a
execProcP2PrcParser = eitherExecProcessParser p2PrcCmdName execProcP2PRCParser = eitherExecProcessParser p2prcCmdName
-- TODO: GHC question, why does it scope down instead staying generic -- TODO: GHC question, why does it scope down instead staying generic
execProcP2Prc = eitherExecProcess p2PrcCmdName -- execProcP2PRC = eitherExecProcess p2prcCmdName

View File

@@ -87,8 +87,8 @@ optsToCLI = concatMap _optToCLI
_optToCLI (MkOptTuple (o, v)) = [o, v] _optToCLI (MkOptTuple (o, v)) = [o, v]
spawnProcP2Prc :: CLICmd -> [CLIOpt] -> IOEitherError ProcessHandle spawnProcP2PRC :: CLICmd -> [CLIOpt] -> IOEitherError ProcessHandle
spawnProcP2Prc cmd opts = spawnProcP2PRC cmd opts =
do do
let prc = proc cmd $ optsToCLI opts let prc = proc cmd $ optsToCLI opts
@@ -115,6 +115,6 @@ eitherErrorDecode esa =
-- assumes the program is ran inside the haskell module in p2prc's repo -- assumes the program is ran inside the haskell module in p2prc's repo
-- assumes that last path segment is "haskell" and that p2prc binary's name is "p2p-rendering-computation" -- assumes that last path segment is "haskell" and that p2prc binary's name is "p2p-rendering-computation"
p2PrcCmdName :: String p2prcCmdName :: String
p2PrcCmdName = "p2p-rendering-computation" p2prcCmdName = "p2p-rendering-computation"

View File

@@ -2,6 +2,7 @@
module Engine module Engine
( runP2PRC ( runP2PRC
, fn
) )
where where
@@ -18,7 +19,7 @@ import System.Process ( terminateProcess )
import API import API
( P2PRCapi(..) ( P2PRCapi(..)
, MapPortRequest(..) , MapPortRequest(..)
, p2prcAPI , p2prcAPI, P2PRCommands
) )
@@ -58,14 +59,10 @@ import API
@ @
-} -}
runP2PRC runP2PRC
:: MapPortRequest -- ^ TCP Port Request :: [P2PRCommands] -- ^ TCP Port Request
-> IO () -> IO ()
runP2PRC runP2PRC [] = putStrLn ""
( MkMapPortRequest runP2PRC nonEmpty@(_:_) =
portNumber
domainName
)
=
let let
-- --
@@ -95,9 +92,10 @@ runP2PRC
( MkP2PRCapi ( MkP2PRCapi
{ startServer = startServer { startServer = startServer
, execInitConfig = execInitConfig -- , execInitConfig = execInitConfig
, execListServers = execListServers , execListServers = execListServers
, execMapPort = execMapPort , execMapPort = execMapPort
, execAddCustomInformation = _
} }
) = p2prcAPI ) = p2prcAPI
@@ -105,18 +103,19 @@ runP2PRC
let let
configValue <- execInitConfig -- configValue <- execInitConfig
-- TODO: get name of host server from config json -- TODO: get name of host server from config json
print configValue -- print configValue
putStrLn "\n\n\n" -- putStrLn "\n\n\n"
eitherStartProcessHandle <- startServer eitherStartProcessHandle <- startServer
case eitherStartProcessHandle of case eitherStartProcessHandle of
(Right startProcessHandle) -> do (Right startProcessHandle) ->
do
let sleepNSecs i = threadDelay (i * 1000000) let sleepNSecs i = threadDelay (i * 1000000)
@@ -125,7 +124,8 @@ runP2PRC
outputStr <- execListServers outputStr <- execListServers
print outputStr print outputStr
mapPortOut <- execMapPort $ MkMapPortRequest portNumber domainName -- mapPortOut <- execMapPort $ MkMapPortRequest portNumber domainName
mapPortOut <- execMapPort $ MkMapPortRequest undefined undefined
case mapPortOut of case mapPortOut of
(Right v) -> print v (Right v) -> print v
@@ -159,3 +159,7 @@ runP2PRC
when (toLower c /= 'q') $ exitOnQ exitF when (toLower c /= 'q') $ exitOnQ exitF
exitF exitF
fn :: undefined
fn = undefined

View File

@@ -1,7 +1,7 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
module JSON module JSON
( P2prcConfig(..) ( P2PRCConfig(..)
, IPAddressTable(..) , IPAddressTable(..)
, IPAddress(..) , IPAddress(..)
, ServerInfo(..) , ServerInfo(..)
@@ -38,11 +38,11 @@ instance FromJSON MapPortResponse where
{-# WARNING P2prcConfig "This type is unstable at the moment due to the P2PRC's library error handling bug. For more information visit: https://github.com/Akilan1999/p2p-rendering-computation/issues/114#issuecomment-2474737015" #-} {-# WARNING P2PRCConfig "This type is unstable at the moment due to the P2PRC's library error handling bug. For more information visit: https://github.com/Akilan1999/p2p-rendering-computation/issues/114#issuecomment-2474737015" #-}
-- | This represents the server configuration that defines its attributes and behaviours in the network, as well as, the location of the runtime persistence artifacts. -- | This represents the server configuration that defines its attributes and behaviours in the network, as well as, the location of the runtime persistence artifacts.
newtype P2prcConfig newtype P2PRCConfig
= MkP2prConfig = MkP2PRCConfig
{ machineName :: String -- ^ Machine Name { machineName :: String -- ^ Machine Name
} deriving Show } deriving Show
@@ -96,13 +96,13 @@ newtype P2prcConfig
-- to have a dedicated port field -- to have a dedicated port field
instance FromJSON P2prcConfig where instance FromJSON P2PRCConfig where
parseJSON (Object o) = do parseJSON (Object o) = do
machineName <- o .: "MachineName" machineName <- o .: "MachineName"
pure pure
$ MkP2prConfig $ MkP2PRCConfig
{ machineName=machineName { machineName=machineName
} }

View File

@@ -49,9 +49,10 @@ module P2PRC
-- ** Interface data types -- ** Interface data types
-- | This section gives an overview on the runtime and host machine interfaces. -- | This section gives an overview on the runtime and host machine interfaces.
, P2PRCapi(..) , P2PRCapi(..)
, P2prcConfig(..) , P2PRCConfig(..)
, MapPortRequest(..) , MapPortRequest(..)
, MapPortResponse(..) , MapPortResponse(..)
, P2PRCommands(..)
-- ** Primitive data types -- ** Primitive data types
-- | These types represent the core data that is communicated between requests and the runtime. -- | These types represent the core data that is communicated between requests and the runtime.
@@ -76,13 +77,14 @@ import JSON
, ServerInfo(..) , ServerInfo(..)
, IPAddress(..) , IPAddress(..)
, MapPortResponse(..) , MapPortResponse(..)
, P2prcConfig(..) , P2PRCConfig(..)
) )
import API import API
( MapPortRequest(..) ( MapPortRequest(..)
, P2PRCapi(..) , P2PRCapi(..)
, p2prcAPI , p2prcAPI
, P2PRCommands(..)
) )

View File

@@ -1 +0,0 @@
z

View File

@@ -0,0 +1,13 @@
{ mkDerivation, aeson, base, bytestring, directory, lib, process
, text
}:
mkDerivation {
pname = "p2prc";
version = "0.1.0.0";
src = ./.;
libraryHaskellDepends = [
aeson base bytestring directory process text
];
description = "P2PRC haskell library";
license = "unknown";
}

View File

@@ -3,10 +3,14 @@ module Main where
import P2PRC import P2PRC
( runP2PRC ( runP2PRC
, MapPortRequest(MkMapPortRequest) , MapPortRequest(MkMapPortRequest)
, P2PRCommands(MapPort)
) )
main :: IO () main :: IO ()
main = main =let
in
runP2PRC runP2PRC
( MkMapPortRequest 8080 "jose.akilan.io" [
) ( MapPort $ MkMapPortRequest 8080 "jose.akilan.io")
]

View File

@@ -44,9 +44,9 @@ class Node:
Upload: int Upload: int
ServerPort: str ServerPort: str
BareMetalSSHPort: str BareMetalSSHPort: str
NAT: str NAT: bool
EscapeImplementation: str EscapeImplementation: str
ProxyServer: str ProxyServer: bool
UnSafeMode: bool UnSafeMode: bool
PublicKey: str PublicKey: str
CustomInformation: str CustomInformation: str
@@ -98,6 +98,21 @@ def ListNodes():
dat: IPAddress = dacite.from_dict(IPAddress,ipTableObject) dat: IPAddress = dacite.from_dict(IPAddress,ipTableObject)
return dat return dat
# Add a root node to P2RRC and overwrites all other nodes.
# To be only added before the network started and with
# the intention of a fresh protocol.
def AddRootNode(ip="", port="") -> bool:
ip = go_string(c_char_p(ip.encode('utf-8')), len(ip))
port = go_string(c_char_p(port.encode('utf-8')), len(port))
p2prc.AddRootNode.restype = c_char_p
res = p2prc.AddRootNode(ip, port)
if str(res).strip("b'") == "Success":
return True
return False
# python function to pass-through custom # python function to pass-through custom
# information to interpret which can be # information to interpret which can be
# interpreted as a DSL. # interpreted as a DSL.

View File

@@ -9,3 +9,6 @@ if __name__ == "__main__":
# Add custom information to the network # Add custom information to the network
if AddCustomInformation("Test"): if AddCustomInformation("Test"):
print("It worked") print("It worked")
if AddRootNode("0.0.0.0", "8081"):
print("It worked for adding root node")

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -3,16 +3,20 @@
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="https://fniessen.github.io/org-html-themes/src/readtheorg_theme/css/search.css"/> #+HTML_HEAD: <link rel="stylesheet" type="text/css" href="https://fniessen.github.io/org-html-themes/src/readtheorg_theme/css/search.css"/>
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style.css"/> #+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style.css"/>
#+attr_html: :width 300px
[[./Colored-On-Light-Image.png]]
* Guide through video
*** The video below shows the setup and usage of P2PRC.
#+attr_html: :class video
[[https://www.youtube.com/watch?v=OMwCpedu5cs][https://i3.ytimg.com/vi/OMwCpedu5cs/maxresdefault.jpg]]
*** Source code: https://github.com/Akilan1999/p2p-rendering-computation
* Introduction * Introduction
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: chapter1-introduction :CUSTOM_ID: chapter1-introduction
:END: :END:
** Abstract
:PROPERTIES:
:CUSTOM_ID: abstract
:END:
This project focuses on creating a framework for running heavy computational tasks that a regular This project focuses on creating a framework for running heavy computational tasks that a regular
computer cannot handle easily. These tasks may include graphically demanding video games, rendering computer cannot handle easily. These tasks may include graphically demanding video games, rendering
3D animations, and performing complex protein folding simulations. The major focus of this project 3D animations, and performing complex protein folding simulations. The major focus of this project
@@ -178,6 +182,110 @@ GLOBAL OPTIONS:
-------------- --------------
* Nix Flake
Nix is a growing ecosystem that allows flexibility on how you develop, build and package software and configurations. It brings all programming languages (and all other tooling) to an equal footing, despite deep design differences. More importantly, integrates all the "packaging" into the context of a "pure" function.
P2PRC aims to become a utility that can be used in various flexible manners and having Nix support is a good alternative to accomplish this goal.
Nix Flake is a format, within the Nix ecosystem, intentionally designed to encourage a standard in packaging distribution. The current packaging assumes that you have "nix flake" installed because it is currently an experimental feature of Nix.
** P2PRC core Go language repo
In case you want to develop, build or integrate using nix, you just need to run either "nix develop" or "nix run" from the command line locally in a cloned git repository or by running "nix run github:akilan1999/p2p-rendering-computation -- --help"
P2PRC library also is ready to be imported into other nix flakes. To accomplish that please make sure to override the target nixpkgs environment in the following manner;
#+begin_example
pkgs = import nixpkgs {
inherit system;
overlays = [
p2prc-flake.overlays.default
];
};
#+end_example
This will make the p2prc executable available in the environment of any application you use.
** P2PRC Haskell library
*** Nix:
The project is structured to provide language bindings to any programming language. The first one being supported in this manner is the Haskell programming language. It provides a bootstrapping script for a new Cabal project with p2prc binary available in the environment and, more relevantly, the Haskell library bindings available in the virtual environment cabal environment.
#+begin_example
nix run git+https://github.com/akilan1999/p2p-rendering-computation#initHaskellProject -- <PROJECT_NAME>
#+end_example
This will generate a new haskell project setup to automatically work with the p2prc development and running environment.
Once completed, you should go into the project directory and copy the nix flake template, necessary to define the project's environment.
#+begin_example
nix flake init -t github:akilan1999/p2p-rendering-computation#haskell
#+end_example
The previous command sets up the flake environment and its dependencies. It will look like the following
#+begin_example
{
description = "Start of Haskell P2PRC flake";
inputs =
{
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-util.url = "github:numtide/flake-utils";
p2prc-flake.url = "github:akilan1999/p2p-rendering-computation";
};
outputs = { nixpkgs, p2prc-flake, flake-utils, ... }:
(flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [
p2prc-flake.overlays.default
p2prc-flake.overlays.bindings
];
};
in {
packages.default = pkgs.haskellPackages.callPackage ./cabal.nix { };
devShells.default = pkgs.haskellPackages.shellFor {
packages = p: [
(p.callPackage ./cabal.nix { })
];
buildInputs = with pkgs; [
p2prc-flake.packages.${system}.default
ghc
cabal2nix
cabal-install
];
shellHook = ''
cabal2nix . > ./cabal.nix
'';
};
}
));
}
#+end_example
The template uses Cabal2Nix which manages the Haskell virtual environment automatically. It applies the system overlays, sets up the shell environment for the project (updating the Cabal2Nix configuration) and packages the main executable.
* Using basic commands * Using basic commands
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: using-basic-commands :CUSTOM_ID: using-basic-commands
@@ -352,6 +460,14 @@ p2prc --mp <port no to map> --dn <domain name to link Mapped port against> --ra
-------------- --------------
*** Add root node
Adds a root node to P2RRC and overwrites all other nodes in the ip table.
To be only added before the network is started and with
the intention of a fresh instance.
#+begin_example
p2prc --arn --ip <root node ip address> -p <root node port no>
#+end_example
* P2P Module Implementation * P2P Module Implementation
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: p2p-module-implementation :CUSTOM_ID: p2p-module-implementation
@@ -363,7 +479,7 @@ to determine upload and download speeds. This valuable information enables users
servers with optimal performance, enhancing their overall network experience. servers with optimal performance, enhancing their overall network experience.
#+caption: UML diagram of P2P module #+caption: UML diagram of P2P module
[[file:images/p2pmoduleArch.png]] [[file:./images/p2pmoduleArch.png]
The peer to peer implementation was built from scratch. This is because The peer to peer implementation was built from scratch. This is because
other peer to peer libraries were on the implementation of the other peer to peer libraries were on the implementation of the
@@ -656,7 +772,24 @@ called from other programming languages.
P2PRC officially supports Haskell bindings and will further support P2PRC officially supports Haskell bindings and will further support
project using Haskell to build orchestrators on top of P2PRC. project using Haskell to build orchestrators on top of P2PRC.
[[https://p2prc.akilan.io/Docs/haskell][Read more...]] **** Local machine without Nix
On the local machine we just create a folder as exports which copies the p2prc haskell bindings
and the latest build of the p2prc binary. After the binary is copied it runs the --dc in p2prc to setup the
basic p2prc configurations. To do the following just do:
#+begin_example
make haskell
#+end_example
**** Directory to enter into
#+begin_example
cd Bindings/Haskell/exports
#+end_example
**** Run
#+begin_example
- cabal build
- cabal run
#+end_example
[[https://p2prc.akilan.io/haskell][Read more...]]
* Config Implementation * Config Implementation
:PROPERTIES: :PROPERTIES:
@@ -678,18 +811,28 @@ configuration file was generated using JSON format.
#+begin_src json #+begin_src json
{ {
"MachineName": "pc-74-120.customer.ask4.lan", "MachineName": "Akilans-MacBook-Pro.local-975261X",
"IPTable": "/Users/akilan/Documents/p2p-rendering-computation/p2p/iptable/ip_table.json", "IPTable": "/Users/akilan/Documents/p2p-rendering-computation/p2p/iptable/ip_table.json",
"DockerContainers": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/", "DockerContainers": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/",
"DefaultDockerFile": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/docker-ubuntu-sshd/", "DefaultDockerFile": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/docker-ubuntu-sshd/",
"DockerRunLogs": "/tmp/",
"SpeedTestFile": "/Users/akilan/Documents/p2p-rendering-computation/p2p/50.bin", "SpeedTestFile": "/Users/akilan/Documents/p2p-rendering-computation/p2p/50.bin",
"IPV6Address": "", "IPV6Address": "",
"PluginPath": "/Users/akilan/Documents/p2p-rendering-computation/plugin/deploy", "PluginPath": "/Users/akilan/Documents/p2p-rendering-computation/plugin/deploy",
"TrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/trackcontainers.json", "TrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/trackcontainers.json",
"ServerPort": "8088", "ServerPort": "8088",
"ProxyPort": "",
"GroupTrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/grouptrackcontainers.json", "GroupTrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/grouptrackcontainers.json",
"FRPServerPort": "True", "FRPServerPort": true,
"BehindNAT": "True", "BehindNAT": true,
"IPTableKey": "QH3yQrGRe2X4",
"PublicKeyFile": "/Users/akilan/Documents/p2p-rendering-computation/p2prc.publicKey",
"PrivateKeyFile": "/Users/akilan/Documents/p2p-rendering-computation/p2prc.privateKey",
"PemFile": "/Users/akilan/Documents/p2p-rendering-computation/cert.pem",
"KeyFile": "/Users/akilan/Documents/p2p-rendering-computation/key.pem",
"BareMetal": false,
"UnsafeMode": false,
"Test": false,
"CustomConfig": null "CustomConfig": null
} }
#+end_src #+end_src
@@ -771,10 +914,48 @@ func main() {
} }
} }
#+end_src #+end_src
* Simulation
The simulation library is a really simple library to locally
run serveral instances of P2PRC to test the functionality
of sending information through the network and particularly
the Node discovery mechanism. There are current 5 commands
which can be used as shown below:
** Command
- ***P2PRC instances "number of instances"*** : Starts p2prc processes
based on the number of number instances provided. This includes
creating temporary folders with independent IPTables.
- ***Start all instances "number of instances"***: Starts the P2PRC instances
created. This function enters into the instance directory and runs
```p2prc -s &``` with a delay for approximately 3 seconds. This allows
each independent created node to learn about each other.
- ***IP Tables after Started number of instances"***: Prints the IPTable of
each independant node.
- ***Remove all test files***: Removes all test files created which needed for
testing the generated P2PRC instances.
- ***Kill all instances***: Kills all the background P2PRC instances created.
** Sample bash instructions
#+begin_src bash
# Unset default P2PRC env path
unset P2PRC
# Run with 2 nodes
P2PRC_instances 3
# Start instances
Start_all_instances 3
# List ip tables of nodes started
IP_Tables_after_Started 3
# Remove test files created
Remove_all_test_files
# Kill all instances
Kill_all_instances
#+end_src
Source code: https://github.com/Akilan1999/p2p-rendering-computation/blob/master/Simulation/simulation.sh
* Blog posts * Blog posts
** Self host within 5 minutes any program ** Self host within 5 minutes any program
@@ -783,6 +964,7 @@ func main() {
- Video tutorial: - Video tutorial:
#+attr_html: :class video
[[https://youtu.be/rN4SiVowg5E][https://i3.ytimg.com/vi/rN4SiVowg5E/maxresdefault.jpg]] [[https://youtu.be/rN4SiVowg5E][https://i3.ytimg.com/vi/rN4SiVowg5E/maxresdefault.jpg]]
This is a fun expirement for anyone to try to quickly run a server and This is a fun expirement for anyone to try to quickly run a server and

1
Docs/kill-docs.sh Normal file
View File

@@ -0,0 +1 @@
kill -9 $(lsof -t -i:8083)

1
Docs/run-docs.sh Normal file
View File

@@ -0,0 +1 @@
go run staticServer.go &

28
Docs/staticServer.go Normal file
View File

@@ -0,0 +1,28 @@
/*
Serve is a very simple static file server in go
Usage:
-p="8100": port to serve on
-d=".": the directory of static files to host
Navigating to http://localhost:8100 will display the index.html or directory
listing file.
*/
package main
import (
"flag"
"log"
"net/http"
)
func main() {
port := flag.String("p", "8083", "port to serve on")
directory := flag.String("d", ".", "the directory of static file to host")
flag.Parse()
http.Handle("/", http.FileServer(http.Dir(*directory)))
log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
log.Fatal(http.ListenAndServe(":"+*port, nil))
}

View File

@@ -23,3 +23,7 @@ h4,h5,h6{
color: #b96c29; color: #b96c29;
font-weight:300; font-weight:300;
} }
.video {
box-shadow: 10px 10px 25px rgba(0, 0, 0, 0.3);
}

View File

@@ -14,6 +14,9 @@ sharedObjects:
python: python:
sh build-python-package.sh sh build-python-package.sh
haskell:
sh build-haskell.sh
clean: clean:
go clean -modcache go clean -modcache
rm -fr .go-build vendor result* rm -fr .go-build vendor result*

View File

@@ -1,5 +1,5 @@
> [!TIP] > [!TIP]
> Haskell bindings supported!: [Bindings documentaton](https://p2prc.akilan.io/Docs/haskell/P2PRC.html) > Haskell bindings supported!: [Bindings documentaton](https://p2prc.akilan.io/haskell/P2PRC.html)
> [!NOTE] > [!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). > 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).
@@ -57,7 +57,7 @@ alias p2prc='env P2PRC=<path you want the configs to exist in> nix run github:ak
```bash ```bash
p2prc -h p2prc -h
``` ```
Read more on command usage: https://p2prc.akilan.io/Docs/#using-basic-commands Read more on command usage: https://p2prc.akilan.io/#using-basic-commands
## Latest tutorial ## Latest tutorial
[![IMAGE ALT TEXT](https://i.ytimg.com/vi/OMwCpedu5cs/hqdefault.jpg)](https://www.youtube.com/watch?v=OMwCpedu5cs") [![IMAGE ALT TEXT](https://i.ytimg.com/vi/OMwCpedu5cs/hqdefault.jpg)](https://www.youtube.com/watch?v=OMwCpedu5cs")
@@ -66,7 +66,7 @@ Read more on command usage: https://p2prc.akilan.io/Docs/#using-basic-commands
## Documentation ## Documentation
### We have documented to our best effort the basics of p2prc: [Link](https://p2prc.akilan.io/Docs/) ### We have documented to our best effort the basics of p2prc: [Link](https://p2prc.akilan.io/)
<!-- ## Table of contents in the current README --> <!-- ## Table of contents in the current README -->
<!-- 1. [Introduction](#Introduction) <!-- 1. [Introduction](#Introduction)

132
Simulation/simulation.sh Normal file
View File

@@ -0,0 +1,132 @@
# Unset P2PRC
unset P2PRC
# Create P2PRC instances
# Parameters:
# 1. Number of nodes
P2PRC_instances() {
local rootPort=""
for (( counter=0; counter<$1; counter++ )); do
mkdir test-$counter/
cd test-$counter/
# Generate a new random port
NEW_PORT=$(shuf -i 2000-65000 -n 1)
# Initialize node
p2prc --dc
# Save rootPort from the first node
if [[ $counter -eq 0 ]]; then
rootPort=$NEW_PORT
fi
echo "Root port: $rootPort"
echo "This node's port: $NEW_PORT"
# Set root port
p2prc --arn --ip 0.0.0.0 -p "$rootPort"
# add current node
p2prc --as 0.0.0.0 -p "$NEW_PORT"
# Replace the ServerPort in config
# test-$counter
sed -i.bak "s/\"ServerPort\": \"[0-9]*\"/\"ServerPort\": \"$NEW_PORT\"/" "./config.json"
sed -i.bak "s/\"Test\": false/\"Test\": true/" "./config.json"
sed -i.bak "s/\"BehindNAT\": true/\"BehindNAT\": false/" "./config.json"
# sed -i.bak "s/\"MachineName\": "Akilans-MacBook-Pro.local-J2UbbkF"/\"MachineName\": \"test-$counter\"/" "./config.json"
cat config.json
# List services
p2prc --ls
cd ..
done
# remove all instances after testing (optional — might want to comment this during testing)
# rm -rf test-*
}
# Arrays of process IDs
pids=()
# Calls all the P2PRC instances created for testing
Start_all_instances() {
for (( counter=0; counter<$1; counter++ )); do
cd test-$counter/
# Start P2PRC as background process
p2prc -s &
pids+=($!)
sleep 3
cd ..
done
}
# Kills all P2PRC instances
Kill_all_instances() {
for pid in "${pids[@]}"; do
kill "$pid"
echo "Killed process $pid"
done
}
# Removes all test files created
Remove_all_test_files() {
rm -rf test-*
}
# List ip tables of all nodes started
IP_Tables_after_Started() {
for (( counter=0; counter<$1; counter++ )); do
cd test-$counter/
p2prc --ls
cd ..
done
}
Update_All_IP_Tables() {
for (( counter=0; counter<$1; counter++ )); do
cd test-$counter/
p2prc --us
cd ..
done
}
# Test function for the root to custom information
# through the network
Send_Information() {
ls
cd test-2/
p2prc --amd "test message"
cd ..
}
# ---------------- Work flow test ---------------
# Unset default P2PRC env path
unset P2PRC
# Run with 2 nodes
P2PRC_instances 3
## Start instances
Start_all_instances 3
# Send test information from node 1
sleep 10
Send_Information
sleep 10
## List ip tables of nodes started
IP_Tables_after_Started 3
#
## Remove test files created
Remove_all_test_files
## Kill all instances
Kill_all_instances

View File

@@ -1,6 +1,5 @@
package abstractions package abstractions
import "C"
import ( import (
"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"
@@ -93,3 +92,17 @@ func UpdateIPTable() (err error) {
func AddCustomInformation(information string) error { func AddCustomInformation(information string) error {
return clientIPTable.AddCustomInformationToIPTable(information) return clientIPTable.AddCustomInformationToIPTable(information)
} }
// AddRootNode Adds root node to the network by using defaults except for
// ip address and port no. Supports only IPV4 as of now.
func AddRootNode(rootIP string, portNo string) error {
var rootNode []p2p.IpAddress
rootNode = append(rootNode, p2p.IpAddress{
Name: "",
Ipv4: rootIP,
ServerPort: portNo,
NAT: false,
})
return generate.GenerateIPTableFile(rootNode)
}

BIN
artwork/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 922 KiB

31
build-haskell.sh Normal file
View File

@@ -0,0 +1,31 @@
# This bash script consists of the manaul build script of haskell
go build .
# Unset p2prc path
unset p2prc
# Enter the haskell project
cd Bindings/haskell
# Remove exsisting export build
rm -rf exports
# Create exports directory
mkdir exports
# Copy current haskell project into the folder
cp -rf . exports/
# Copy p2prc binary inside haskell folder
cp ../../p2p-rendering-computation exports/
cd exports
# remove exports directory copied inside exports
rm -rf exports/
# Set p2prc variable
echo export P2PRC=$PWD
export P2PRC=$PWD
./p2p-rendering-computation --dc
echo "Run the following commands in the directory: ${PWD}"
echo "To build: cabal build"
echo "To run sample program: cabal run"

View File

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

View File

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

View File

@@ -2,8 +2,10 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/Akilan1999/p2p-rendering-computation/abstractions"
"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"
Config "github.com/Akilan1999/p2p-rendering-computation/config"
"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"
@@ -87,11 +89,7 @@ var CliAction = func(ctx *cli.Context) error {
// 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)
standardOutput(err, imageRes)
if err != nil {
fmt.Print(err)
}
client.PrettyPrint(imageRes)
} }
// Function called to stop and remove server from Docker // Function called to stop and remove server from Docker
@@ -100,9 +98,7 @@ var CliAction = func(ctx *cli.Context) error {
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 { standardOutput(err, nil)
fmt.Print(err)
}
} }
} }
@@ -119,58 +115,40 @@ var CliAction = func(ctx *cli.Context) error {
// 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, BaseImage) imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName, BaseImage)
if err != nil { standardOutput(err, imageRes)
fmt.Print(err)
}
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 { standardOutput(err, specs)
return err
}
// Pretty print
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 { standardOutput(err, nil)
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 { standardOutput(err, nil)
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 { standardOutput(err, plugins)
fmt.Print(err)
}
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 { standardOutput(err, trackedContainers)
fmt.Print(err)
}
client.PrettyPrint(trackedContainers)
} }
//Executing plugin when the plugin flag is called //Executing plugin when the plugin flag is called
@@ -179,14 +157,11 @@ var CliAction = func(ctx *cli.Context) error {
// 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 { standardOutput(err, nil)
fmt.Println(err)
} else {
fmt.Println("Success")
}
} else {
fmt.Println("provide container ID via --ID or --id")
} }
//else {
// fmt.Println("provide container ID via --ID or --id")
//}
} }
@@ -194,10 +169,7 @@ var CliAction = func(ctx *cli.Context) error {
// 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 { standardOutput(err, group)
return err
}
client.PrettyPrint(group)
} }
// Actions to be performed when the // Actions to be performed when the
@@ -208,26 +180,14 @@ var CliAction = func(ctx *cli.Context) error {
// --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 { standardOutput(err, group)
fmt.Println(err)
} else {
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 { standardOutput(err, group)
fmt.Println(err)
} else {
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 { standardOutput(err, group)
fmt.Println(err)
} else {
client.PrettyPrint(group)
}
} }
} }
@@ -236,63 +196,58 @@ var CliAction = func(ctx *cli.Context) error {
// --rmgroup // --rmgroup
if RemoveGroup != "" { if RemoveGroup != "" {
err := client.RemoveGroup(RemoveGroup) err := client.RemoveGroup(RemoveGroup)
if err != nil { standardOutput(err, nil)
fmt.Println(err)
} else {
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 { standardOutput(err, groups)
fmt.Println(err)
} else {
client.PrettyPrint(groups)
}
} }
//-------------------------------- //--------------------------------
if PullPlugin != "" { if PullPlugin != "" {
err := plugin.DownloadPlugin(PullPlugin) err := plugin.DownloadPlugin(PullPlugin)
if err != nil { standardOutput(err, nil)
fmt.Println(err)
} else {
fmt.Println("Success")
}
} }
if RemovePlugin != "" { if RemovePlugin != "" {
err := plugin.DeletePlugin(RemovePlugin) err := plugin.DeletePlugin(RemovePlugin)
if err != nil { standardOutput(err, nil)
fmt.Println(err)
} else {
fmt.Println("Success")
}
} }
if AddMetaData != "" { if AddMetaData != "" {
err := clientIPTable.AddCustomInformationToIPTable(AddMetaData) err := clientIPTable.AddCustomInformationToIPTable(AddMetaData)
if err != nil { standardOutput(err, nil)
fmt.Println(err)
} else {
fmt.Println("Success")
}
} }
if MAPPort != "" { if MAPPort != "" {
address, err := client.MAPPort(MAPPort, DomainName, RemoteAddress) address, err := client.MAPPort(MAPPort, DomainName, RemoteAddress)
if err != nil { standardOutput(err, address)
return err }
}
if err != nil { // Action called to add root node to network
fmt.Println(err) if AddRootNode && IP != "" && Ports != "" {
} else { err := abstractions.AddRootNode(IP, Ports)
client.PrettyPrint(address) standardOutput(err, nil)
} }
// display configuration
if ViewConfig {
config, err := Config.ConfigInit(nil, nil)
standardOutput(err, config)
} }
return nil return nil
} }
func standardOutput(err error, i interface{}) {
if err != nil {
fmt.Println(err)
} else if i == nil {
fmt.Println("Success")
} else {
client.PrettyPrint(i)
}
}

View File

@@ -41,6 +41,9 @@ var (
PullPlugin string PullPlugin string
RemovePlugin string RemovePlugin string
AddMetaData string AddMetaData string
AddRootNode bool
IP string
ViewConfig bool
) )
var AppConfigFlags = []cli.Flag{ var AppConfigFlags = []cli.Flag{
@@ -272,4 +275,25 @@ var AppConfigFlags = []cli.Flag{
EnvVars: []string{"ADDMETADATA"}, EnvVars: []string{"ADDMETADATA"},
Destination: &AddMetaData, Destination: &AddMetaData,
}, },
&cli.BoolFlag{
Name: "AddRootNode",
Aliases: []string{"arn"},
Usage: "Adds initial root node to talk to",
EnvVars: []string{"ADDROOTNODE"},
Destination: &AddRootNode,
},
&cli.StringFlag{
Name: "IPAddress",
Aliases: []string{"ip"},
Usage: "IP address",
EnvVars: []string{"IP"},
Destination: &IP,
},
&cli.BoolFlag{
Name: "ViewConfig",
Aliases: []string{"vc"},
Usage: "View config file",
EnvVars: []string{"VC"},
Destination: &ViewConfig,
},
} }

View File

@@ -29,8 +29,8 @@ type Config struct {
ServerPort string ServerPort string
ProxyPort string ProxyPort string
GroupTrackContainersPath string GroupTrackContainersPath string
FRPServerPort string FRPServerPort bool
BehindNAT string BehindNAT bool
IPTableKey string IPTableKey string
PublicKeyFile string PublicKeyFile string
PrivateKeyFile string PrivateKeyFile string
@@ -38,7 +38,9 @@ type Config struct {
KeyFile string KeyFile string
BareMetal bool BareMetal bool
UnsafeMode bool UnsafeMode bool
Test bool
CustomConfig interface{} CustomConfig interface{}
ConfigPath string
//NetworkInterface string //NetworkInterface string
//NetworkInterfaceIPV6Index int //NetworkInterfaceIPV6Index int
} }

View File

@@ -78,9 +78,9 @@ func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, No
Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json" Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json"
Defaults.ServerPort = "8088" Defaults.ServerPort = "8088"
Defaults.ProxyPort = "" Defaults.ProxyPort = ""
Defaults.FRPServerPort = "True" Defaults.FRPServerPort = true
Defaults.CustomConfig = CustomConfig Defaults.CustomConfig = CustomConfig
Defaults.BehindNAT = "True" Defaults.BehindNAT = true
Defaults.DockerRunLogs = "/tmp/" Defaults.DockerRunLogs = "/tmp/"
// Generate a random key to be added to IPTable // Generate a random key to be added to IPTable
Defaults.IPTableKey = String(12) Defaults.IPTableKey = String(12)
@@ -95,6 +95,8 @@ func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, No
Defaults.PrivateKeyFile = defaultPath + "p2prc.privateKey" Defaults.PrivateKeyFile = defaultPath + "p2prc.privateKey"
Defaults.BareMetal = false Defaults.BareMetal = false
Defaults.UnsafeMode = false Defaults.UnsafeMode = false
Defaults.Test = false
Defaults.ConfigPath = defaultPath + "config.json"
// Generate certificate files for SSL // Generate certificate files for SSL
err = GenerateCertificate() err = GenerateCertificate()

View File

@@ -16,7 +16,6 @@ import (
"crypto/x509" "crypto/x509"
"crypto/x509/pkix" "crypto/x509/pkix"
"encoding/pem" "encoding/pem"
"github.com/Akilan1999/p2p-rendering-computation/p2p"
"log" "log"
"math/big" "math/big"
"net" "net"
@@ -54,7 +53,8 @@ func GenerateCertificate() error {
//flag.Parse() //flag.Parse()
host, err = p2p.CurrentPublicIP() //host, err = p2p.CurrentPublicIP()
host = "0.0.0.0"
if err != nil { if err != nil {
return err return err

View File

@@ -45,9 +45,9 @@ func GenerateIPTableFile(rootNodes []p2p.IpAddress) (err error) {
if len(rootNodes) <= 0 { if len(rootNodes) <= 0 {
rootnode.Name = "Node1" rootnode.Name = "Node1"
rootnode.ServerPort = "8078" rootnode.ServerPort = "8078"
rootnode.NAT = "False" rootnode.NAT = false
rootnode.Ipv4 = "217.76.63.222" rootnode.Ipv4 = "217.76.63.222"
rootnode.ProxyServer = "True" rootnode.ProxyServer = true
rootnodes.IpAddress = append(rootnodes.IpAddress, rootnode) rootnodes.IpAddress = append(rootnodes.IpAddress, rootnode)
} else { } else {

12
flake.lock generated
View File

@@ -28,11 +28,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1733668782, "lastModified": 1745875161,
"narHash": "sha256-tPsqU00FhgdFr0JiQUiBMgPVbl1jbPCY5gbFiJycL3I=", "narHash": "sha256-0YkWCS13jpoo3+sX/3kcgdxBNt1VZTmvF+FhZb4rFKI=",
"owner": "nix-community", "owner": "nix-community",
"repo": "gomod2nix", "repo": "gomod2nix",
"rev": "514283ec89c39ad0079ff2f3b1437404e4cba608", "rev": "2cbd7fdd6eeab65c494cc426e18f4e4d2a5e35c0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -43,11 +43,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1735834308, "lastModified": 1748460289,
"narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", "narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6df24922a1400241dae323af55f30e4318a6ca65", "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102",
"type": "github" "type": "github"
}, },
"original": { "original": {

152
flake.nix
View File

@@ -1,41 +1,129 @@
{ {
description = "P2PRC nix flake"; description = "P2PRC nix flake";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; inputs = {
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.gomod2nix.url = "github:nix-community/gomod2nix";
inputs.gomod2nix.inputs.nixpkgs.follows = "nixpkgs";
inputs.gomod2nix.inputs.flake-utils.follows = "flake-utils";
outputs = { self, nixpkgs, flake-utils, gomod2nix }: nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
(flake-utils.lib.eachDefaultSystem
(system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ gomod2nix.overlays.default ];
};
# pkgs = nixpkgs.legacyPackages.${system}; flake-utils = {
url = "github:numtide/flake-utils";
};
# The current default sdk for macOS fails to compile go projects, so we use a newer one for now. gomod2nix = {
# This has no effect on other platforms. url = "github:nix-community/gomod2nix";
callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage; inputs.nixpkgs.follows = "nixpkgs";
in inputs.flake-utils.follows = "flake-utils";
{ };
packages.default = callPackage ./. { }; };
devShells.default = pkgs.mkShell { outputs =
buildInputs = with pkgs; [ {
go nixpkgs,
gopls flake-utils,
gotools gomod2nix,
go-tools ...
gomod2nix.packages.${system}.default }:
sqlite-interactive let
];
}; bindingsOverlay = import ./nix/overlays/bindings.nix;
}) coreOverlay = (final: prev: {
); p2prc = final.callPackage ./. { };
});
in
(flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [
gomod2nix.overlays.default
coreOverlay
bindingsOverlay
];
};
# The current default sdk for macOS fails to compile go projects, so we use a newer one for now.
# This has no effect on other platforms.
callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage;
p2prcDefault = callPackage ./. { };
in
{
packages.default = p2prcDefault;
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
go
gopls
gotools
go-tools
gomod2nix.packages.${system}.default
sqlite-interactive
];
};
packages.initHaskellProject = pkgs.writeShellApplication {
name = "initHaskellProject";
runtimeInputs = with pkgs; [
ghc
cabal2nix
cabal-install
git
p2prcDefault
];
text =
''
clear
if [ "$#" -eq 0 ]; then
echo "No arguments provided."
echo "Please provide the name of your project"
echo "nix run git+https://github:akilan1999/p2p-rendering-computation#initHaskellProject -- <NAME-PROJECT>"
exit 1;
fi
PROJECT_DIR="$1"
mkdir "$PROJECT_DIR"
cd "$PROJECT_DIR"
git init .
clear
cabal init --exe --simple
sed -i 's/base.*$/base, p2prc/' "$PROJECT_DIR".cabal
cabal2nix . > ./cabal.nix;
git add .
clear
echo -e "run the following commands to finish nix development and production environment:\n\n"
echo -e "cd $PROJECT_DIR"
echo -e "nix flake init -t github:akilan1999/p2p-rendering-computation#haskell"
echo -e "nix develop"
echo -e "nix run"
echo -e "\n\n"
'';
};
}
)) //
{
overlays = {
default = coreOverlay;
bindings = bindingsOverlay;
};
templates.haskell = {
path = ./nix/templates/haskell;
description = "Haskell Bindings to p2prc protocol";
};
};
} }

View File

@@ -0,0 +1,7 @@
final: prev: {
haskellPackages = prev.haskellPackages.override {
overrides = hfinal: hprev: {
p2prc = hfinal.callPackage ../../Bindings/Haskell/project.nix { };
};
};
}

190
nix/templates/haskell/flake.lock generated Normal file
View File

@@ -0,0 +1,190 @@
{
"nodes": {
"flake-util": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"id": "flake-utils",
"type": "indirect"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_3"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"flake-utils": [
"p2prc-flake",
"flake-utils"
],
"nixpkgs": [
"p2prc-flake",
"nixpkgs"
]
},
"locked": {
"lastModified": 1745875161,
"narHash": "sha256-0YkWCS13jpoo3+sX/3kcgdxBNt1VZTmvF+FhZb4rFKI=",
"owner": "nix-community",
"repo": "gomod2nix",
"rev": "2cbd7fdd6eeab65c494cc426e18f4e4d2a5e35c0",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "gomod2nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1748460289,
"narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1748370509,
"narHash": "sha256-QlL8slIgc16W5UaI3w7xHQEP+Qmv/6vSNTpoZrrSlbk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4faa5f5321320e49a78ae7848582f684d64783e9",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"p2prc-flake": {
"inputs": {
"flake-utils": "flake-utils_2",
"gomod2nix": "gomod2nix",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1748646470,
"narHash": "sha256-7aZQQ+jHdlxUzFPXzEEYfH1oU3isSZlZnMC7HWUDHCk=",
"owner": "xecarlox94",
"repo": "p2p-rendering-computation",
"rev": "73a283a545d61754a0fe821287541c2cd412bc0e",
"type": "github"
},
"original": {
"owner": "xecarlox94",
"ref": "nix",
"repo": "p2p-rendering-computation",
"type": "github"
}
},
"root": {
"inputs": {
"flake-util": "flake-util",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"p2prc-flake": "p2prc-flake"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View File

@@ -0,0 +1,48 @@
{
description = "Start of Haskell P2PRC flake";
inputs =
{
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-util.url = "github:numtide/flake-utils";
p2prc-flake.url = "github:akilan1999/p2p-rendering-computation";
};
outputs = { nixpkgs, p2prc-flake, flake-utils, ... }:
(flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [
p2prc-flake.overlays.default
p2prc-flake.overlays.bindings
];
};
in {
packages.default = pkgs.haskellPackages.callPackage ./cabal.nix { };
devShells.default = pkgs.haskellPackages.shellFor {
packages = p: [
(p.callPackage ./cabal.nix { })
];
buildInputs = with pkgs; [
p2prc-flake.packages.${system}.default
ghc
cabal2nix
cabal-install
];
shellHook = ''
cabal2nix . > ./cabal.nix
'';
};
}
));
}

View File

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

View File

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

View File

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

View File

@@ -1,32 +0,0 @@
body {
font-family: sans-serif;
}
span#discordJoin {
color: red;
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
/* General Page Changing */
body {
background: #121212; /* Background Color */
color: #FFFFFF; /* Text Color */
}
a:link{ /* Unvisited Link */
color: #03DAC5;
}
a:visited { /* Visited Link */
color: #BB86FC;
}
a:hover { /* Mouse over Link */
color: #018786;
}
span#discordJoin { /* Text Color Change */
color: #cc0227;
}
}

BIN
wasm/p2prc.wasm Executable file

Binary file not shown.