96 Commits

Author SHA1 Message Date
ac2c5f8a83 test changes 2025-06-02 18:25:05 +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
5f8407a37f added comment 2025-04-24 23:28:19 +01:00
a6939ec35e added python function call add custom information 2025-04-24 23:15:02 +01:00
Akilan Selvacoumar
c445ac88c4 Merge pull request #124 from Akilan1999/python-bindings
Python bindings (Base function calls)
2025-04-24 22:17:02 +01:00
44 changed files with 2345 additions and 844 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

View File

@@ -142,6 +142,24 @@ func MapPort(Port string, DomainName string, ServerAddress string) *C.char {
return C.CString(Address.EntireAddress)
}
//export CustomInformation
func CustomInformation(CustomInformation string) *C.char {
err := abstractions.AddCustomInformation(CustomInformation)
if err != nil {
return C.CString(err.Error())
}
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 ----------------------------------------
//export Server

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

View File

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

View File

@@ -20,19 +20,21 @@ import Error
import JSON
( IPAddressTable(..)
, MapPortResponse(..)
, P2prcConfig
, P2PRCConfig
)
import CLI
( StdInput(..)
, CLIOpt(..)
, eitherErrDecode
, p2PrcCmdName
, p2prcCmdName
, eitherExecProcess
, eitherExecProcessParser
, spawnProcP2Prc
, spawnProcP2PRC
)
-- import System.Environment (lookupEnv)
-- | Lower level P2PRC Haskell api that exposes basic functionality necessary to joint the network.
@@ -41,7 +43,7 @@ data P2PRCapi
= MkP2PRCapi
{ startServer :: IOEitherError ProcessHandle
-- ^ Start server
, execInitConfig :: IOEitherError P2prcConfig
-- , execInitConfig :: IOEitherError P2PRCConfig
-- ^ Instantiate server configuration
, execListServers :: IOEitherError IPAddressTable
-- ^ List servers in network
@@ -94,14 +96,14 @@ main =
p2prcAPI :: P2PRCapi
p2prcAPI =
MkP2PRCapi
{ startServer = spawnProcP2Prc p2PrcCmdName [ MkOptAtomic "--s" ]
{ startServer = spawnProcP2PRC p2prcCmdName [ MkOptAtomic "--s" ]
, execListServers =
execProcP2PrcParser [ MkOptAtomic "--ls" ] MkEmptyStdInput
execProcP2PRCParser [ MkOptAtomic "--ls" ] MkEmptyStdInput
, execMapPort =
\ (MkMapPortRequest portNumber domainName) ->
execProcP2PrcParser
execProcP2PRCParser
[ MkOptTuple
( "--mp"
, show portNumber
@@ -113,39 +115,41 @@ p2prcAPI =
]
MkEmptyStdInput
, execInitConfig = do
-- , execInitConfig = do
confInitRes <- execProcP2Prc [ MkOptAtomic "--dc" ] MkEmptyStdInput
-- confInitRes <- execProcP2PRC [ MkOptAtomic "--dc" ] MkEmptyStdInput
case confInitRes of
(Right _) -> do
-- case confInitRes of
-- (Right _) -> do
-- TODO: get config file name dynamically
--
currDirectory <- getCurrentDirectory
-- maybeValue <- lookupEnv "P2PRC"
-- TODO: change values before loading file
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
configContent <- readFile fname
-- -- TODO: read config check if file exists
-- configContent <- readFile fname
pure $ eitherErrDecode configContent
-- pure $ eitherErrDecode configContent
(Left err) -> pure $ Left err
-- (Left err) -> pure $ Left err
}
where
execProcP2PrcParser ::
execProcP2PRCParser ::
FromJSON a =>
[CLIOpt] -> StdInput -> IOEitherError a
execProcP2PrcParser = eitherExecProcessParser p2PrcCmdName
execProcP2PRCParser = eitherExecProcessParser p2prcCmdName
-- 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]
spawnProcP2Prc :: CLICmd -> [CLIOpt] -> IOEitherError ProcessHandle
spawnProcP2Prc cmd opts =
spawnProcP2PRC :: CLICmd -> [CLIOpt] -> IOEitherError ProcessHandle
spawnProcP2PRC cmd opts =
do
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 that last path segment is "haskell" and that p2prc binary's name is "p2p-rendering-computation"
p2PrcCmdName :: String
p2PrcCmdName = "p2p-rendering-computation"
p2prcCmdName :: String
p2prcCmdName = "p2p-rendering-computation"

View File

@@ -95,7 +95,7 @@ runP2PRC
( MkP2PRCapi
{ startServer = startServer
, execInitConfig = execInitConfig
-- , execInitConfig = execInitConfig
, execListServers = execListServers
, execMapPort = execMapPort
}
@@ -105,12 +105,12 @@ runP2PRC
let
configValue <- execInitConfig
-- configValue <- execInitConfig
-- TODO: get name of host server from config json
print configValue
putStrLn "\n\n\n"
-- print configValue
-- putStrLn "\n\n\n"
eitherStartProcessHandle <- startServer

View File

@@ -1,7 +1,7 @@
{-# LANGUAGE OverloadedStrings #-}
module JSON
( P2prcConfig(..)
( P2PRCConfig(..)
, IPAddressTable(..)
, IPAddress(..)
, 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.
newtype P2prcConfig
= MkP2prConfig
newtype P2PRCConfig
= MkP2PRCConfig
{ machineName :: String -- ^ Machine Name
} deriving Show
@@ -96,13 +96,13 @@ newtype P2prcConfig
-- to have a dedicated port field
instance FromJSON P2prcConfig where
instance FromJSON P2PRCConfig where
parseJSON (Object o) = do
machineName <- o .: "MachineName"
pure
$ MkP2prConfig
$ MkP2PRCConfig
{ machineName=machineName
}

View File

@@ -49,7 +49,7 @@ module P2PRC
-- ** Interface data types
-- | This section gives an overview on the runtime and host machine interfaces.
, P2PRCapi(..)
, P2prcConfig(..)
, P2PRCConfig(..)
, MapPortRequest(..)
, MapPortResponse(..)
@@ -76,7 +76,7 @@ import JSON
, ServerInfo(..)
, IPAddress(..)
, MapPortResponse(..)
, P2prcConfig(..)
, P2PRCConfig(..)
)
import API

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

@@ -44,9 +44,9 @@ class Node:
Upload: int
ServerPort: str
BareMetalSSHPort: str
NAT: str
NAT: bool
EscapeImplementation: str
ProxyServer: str
ProxyServer: bool
UnSafeMode: bool
PublicKey: str
CustomInformation: str
@@ -97,6 +97,33 @@ def ListNodes():
ipTableObject = json.loads((str(ipTable).strip("b'")))
dat: IPAddress = dacite.from_dict(IPAddress,ipTableObject)
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
# information to interpret which can be
# interpreted as a DSL.
def AddCustomInformation(message="") -> bool:
message = go_string(c_char_p(message.encode('utf-8')), len(message))
p2prc.CustomInformation.restype = c_char_p
status = p2prc.CustomInformation(message)
if str(status).strip("b'") == "Success":
return True
return False

View File

@@ -5,3 +5,10 @@ if __name__ == "__main__":
P2PRCNodes = ListNodes()
# Print nodes in the network
print(P2PRCNodes)
# Add custom information to the network
if AddCustomInformation("Test"):
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="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
:PROPERTIES:
:CUSTOM_ID: chapter1-introduction
:END:
** Abstract
:PROPERTIES:
:CUSTOM_ID: abstract
:END:
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
3D animations, and performing complex protein folding simulations. The major focus of this project
@@ -352,6 +356,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
:PROPERTIES:
:CUSTOM_ID: p2p-module-implementation
@@ -363,7 +375,7 @@ to determine upload and download speeds. This valuable information enables users
servers with optimal performance, enhancing their overall network experience.
#+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
other peer to peer libraries were on the implementation of the
@@ -678,18 +690,28 @@ configuration file was generated using JSON format.
#+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",
"DockerContainers": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/",
"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",
"IPV6Address": "",
"PluginPath": "/Users/akilan/Documents/p2p-rendering-computation/plugin/deploy",
"TrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/trackcontainers.json",
"ServerPort": "8088",
"ProxyPort": "",
"GroupTrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/grouptrackcontainers.json",
"FRPServerPort": "True",
"BehindNAT": "True",
"FRPServerPort": 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
}
#+end_src
@@ -771,10 +793,48 @@ func main() {
}
}
#+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
** Self host within 5 minutes any program
@@ -783,6 +843,7 @@ func main() {
- Video tutorial:
#+attr_html: :class video
[[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

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;
font-weight:300;
}
.video {
box-shadow: 10px 10px 25px rgba(0, 0, 0, 0.3);
}

114
Simulation/simulation.sh Normal file
View File

@@ -0,0 +1,114 @@
# 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
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"
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
}
# ---------------- Work flow test ---------------
# 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

View File

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

View File

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

View File

@@ -2,6 +2,7 @@ package cmd
import (
"fmt"
"github.com/Akilan1999/p2p-rendering-computation/abstractions"
"github.com/Akilan1999/p2p-rendering-computation/client"
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
"github.com/Akilan1999/p2p-rendering-computation/config/generate"
@@ -87,11 +88,7 @@ var CliAction = func(ctx *cli.Context) error {
// Displays all images available on the server side
if ViewImages != "" {
imageRes, err := client.ViewContainers(ViewImages)
if err != nil {
fmt.Print(err)
}
client.PrettyPrint(imageRes)
standardOutput(err, imageRes)
}
// Function called to stop and remove server from Docker
@@ -100,9 +97,7 @@ var CliAction = func(ctx *cli.Context) error {
fmt.Println("provide container ID via --ID or --id")
} else {
err := client.RemoveContianer(RemoveVM, ID)
if err != nil {
fmt.Print(err)
}
standardOutput(err, nil)
}
}
@@ -119,58 +114,40 @@ var CliAction = func(ctx *cli.Context) error {
// Calls function to do Api call to start the container on the server side
imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName, BaseImage)
if err != nil {
fmt.Print(err)
}
client.PrettyPrint(imageRes)
standardOutput(err, imageRes)
}
//Call if specs flag is called
if Specs != "" {
specs, err := client.GetSpecs(Specs)
if err != nil {
return err
}
// Pretty print
client.PrettyPrint(specs)
standardOutput(err, specs)
}
//Sets default paths to the config file
if SetDefaultConfig {
_, err := generate.SetDefaults("P2PRC", false, nil, false)
if err != nil {
fmt.Print(err)
}
standardOutput(err, nil)
}
//If the network interface flag is called
// Then all the network interfaces are displayed
if NetworkInterface {
err := p2p.ViewNetworkInterface()
if err != nil {
fmt.Print(err)
}
standardOutput(err, nil)
}
// If the view plugin flag is called then display all
// plugins available
if ViewPlugin {
plugins, err := plugin.DetectPlugins()
if err != nil {
fmt.Print(err)
}
client.PrettyPrint(plugins)
standardOutput(err, plugins)
}
// If the flag Tracked Container is called or the flag
// --tc
if TrackedContainers {
err, trackedContainers := client.ViewTrackedContainers()
if err != nil {
fmt.Print(err)
}
client.PrettyPrint(trackedContainers)
standardOutput(err, trackedContainers)
}
//Executing plugin when the plugin flag is called
@@ -179,14 +156,11 @@ var CliAction = func(ctx *cli.Context) error {
// To execute plugin requires the container ID or group ID provided when being executed
if ID != "" {
err := plugin.CheckRunPlugin(ExecutePlugin, ID)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Success")
}
} else {
fmt.Println("provide container ID via --ID or --id")
standardOutput(err, nil)
}
//else {
// fmt.Println("provide container ID via --ID or --id")
//}
}
@@ -194,10 +168,7 @@ var CliAction = func(ctx *cli.Context) error {
// Creates new group and outputs JSON file
if CreateGroup {
group, err := client.CreateGroup()
if err != nil {
return err
}
client.PrettyPrint(group)
standardOutput(err, group)
}
// Actions to be performed when the
@@ -208,26 +179,14 @@ var CliAction = func(ctx *cli.Context) error {
// --rmcgroup --id <contianer id>
if RemoveContainerGroup && ID != "" {
group, err := client.RemoveContainerGroup(ID, Group)
if err != nil {
fmt.Println(err)
} else {
client.PrettyPrint(group)
}
standardOutput(err, group)
} else if ID != "" { // Add container to group based on group ID provided
// --id <Container ID>
group, err := client.AddContainerToGroup(ID, Group)
if err != nil {
fmt.Println(err)
} else {
client.PrettyPrint(group)
}
standardOutput(err, group)
} else { // View all information about current group
group, err := client.GetGroup(Group)
if err != nil {
fmt.Println(err)
} else {
client.PrettyPrint(group)
}
standardOutput(err, group)
}
}
@@ -236,63 +195,52 @@ var CliAction = func(ctx *cli.Context) error {
// --rmgroup
if RemoveGroup != "" {
err := client.RemoveGroup(RemoveGroup)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Group Removed")
}
standardOutput(err, nil)
}
// Execute Function to view all groups
if Groups {
groups, err := client.ReadGroup()
if err != nil {
fmt.Println(err)
} else {
client.PrettyPrint(groups)
}
standardOutput(err, groups)
}
//--------------------------------
if PullPlugin != "" {
err := plugin.DownloadPlugin(PullPlugin)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Success")
}
standardOutput(err, nil)
}
if RemovePlugin != "" {
err := plugin.DeletePlugin(RemovePlugin)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Success")
}
standardOutput(err, nil)
}
if AddMetaData != "" {
err := clientIPTable.AddCustomInformationToIPTable(AddMetaData)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Success")
}
standardOutput(err, nil)
}
if MAPPort != "" {
address, err := client.MAPPort(MAPPort, DomainName, RemoteAddress)
if err != nil {
return err
}
if err != nil {
fmt.Println(err)
} else {
client.PrettyPrint(address)
}
standardOutput(err, address)
}
// Action called to add root node to network
if AddRootNode && IP != "" && Ports != "" {
err := abstractions.AddRootNode(IP, Ports)
standardOutput(err, 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,8 @@ var (
PullPlugin string
RemovePlugin string
AddMetaData string
AddRootNode bool
IP string
)
var AppConfigFlags = []cli.Flag{
@@ -272,4 +274,18 @@ var AppConfigFlags = []cli.Flag{
EnvVars: []string{"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,
},
}

View File

@@ -29,8 +29,8 @@ type Config struct {
ServerPort string
ProxyPort string
GroupTrackContainersPath string
FRPServerPort string
BehindNAT string
FRPServerPort bool
BehindNAT bool
IPTableKey string
PublicKeyFile string
PrivateKeyFile string
@@ -38,6 +38,7 @@ type Config struct {
KeyFile string
BareMetal bool
UnsafeMode bool
Test bool
CustomConfig interface{}
//NetworkInterface string
//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.ServerPort = "8088"
Defaults.ProxyPort = ""
Defaults.FRPServerPort = "True"
Defaults.FRPServerPort = true
Defaults.CustomConfig = CustomConfig
Defaults.BehindNAT = "True"
Defaults.BehindNAT = true
Defaults.DockerRunLogs = "/tmp/"
// Generate a random key to be added to IPTable
Defaults.IPTableKey = String(12)
@@ -95,6 +95,7 @@ func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, No
Defaults.PrivateKeyFile = defaultPath + "p2prc.privateKey"
Defaults.BareMetal = false
Defaults.UnsafeMode = false
Defaults.Test = false
// Generate certificate files for SSL
err = GenerateCertificate()

View File

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

View File

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

12
flake.lock generated
View File

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

170
flake.nix
View File

@@ -1,41 +1,147 @@
{
description = "P2PRC nix flake";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
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";
inputs = {
outputs = { self, nixpkgs, flake-utils, gomod2nix }:
(flake-utils.lib.eachDefaultSystem
(system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ gomod2nix.overlays.default ];
};
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# 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.
# This has no effect on other platforms.
callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage;
in
{
gomod2nix = {
url = "github:nix-community/gomod2nix";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-utils.follows = "flake-utils";
};
packages.default = callPackage ./. { };
};
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
go
gopls
gotools
go-tools
gomod2nix.packages.${system}.default
sqlite-interactive
];
};
})
);
outputs =
{
nixpkgs,
flake-utils,
gomod2nix,
...
}:
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 =
let
# TODO: add the content for the main file
# p2prcMainContent = availablePort: availableUrl:
# ''
# module Main where
#
# import P2PRC
# ( runP2PRC
# , MapPortRequest(MkMapPortRequest)
# )
#
# main :: IO ()
# main =
# runP2PRC
# ( MkMapPortRequest ${availablePort} "${availableUrl}.akilan.io"
# )
# '';
#
# mainFileContent = p2prcMainContent (builtins.toString 8080) "haskell";
in
''
clear
if [ "$#" -eq 0 ]; then
echo "No arguments provided."
echo "Please provide the name of your project"
echo "nix run 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;
cabal2nix . --shell > shell.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"
'';
};
}
)) //
{
overlays = {
default = coreOverlay;
bindings = bindingsOverlay;
};
templates.haskell = {
path = ./nix/templates/haskell;
description = "Haskell Bindings to p2prc protocol";
};
};
}

909
index.org~ Normal file
View File

@@ -0,0 +1,909 @@
#+SETUPFILE: https://fniessen.github.io/org-html-themes/org/theme-readtheorg.setup
#+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"/>
#+attr_html: :width 300px :align center
[[./artwork/p2prc-logos/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]]
* Introduction
:PROPERTIES:
:CUSTOM_ID: chapter1-introduction
:END:
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
3D animations, and performing complex protein folding simulations. The major focus of this project
is not on financial incentives but rather on building a robust and efficient peer-to-peer (P2P)
network to decentralise task execution and increase the computational bandwidth available for
such tasks.
The P2PRC framework serves as a foundation for decentralised rendering and computation,
providing insights into how tasks can be distributed efficiently across a network of peers.
Leveraging the P2PRC approach, this project extends its capabilities to handle a
wider range of computationally intensive tasks.
** Motivation
:PROPERTIES:
:CUSTOM_ID: motivation
:END:
Many of the users rely on our PC / Laptop or servers that belong to a
server farm to run heavy tasks and with the demand of high creativity
requires higher computing power. Buying a powerful computer every few
years to run a bunch of heavy tasks which are not executed as frequently
to reap the benefits can be inefficient utilization of hardware. On the
other end, renting servers to run these heavy tasks can be really
useful. Ethically speaking this is leading to monopolisation of
computing power similar to what is happening in the web server area. By
using peer to peer principles it is possible to remove the
monopolisation factor and increase the bandwidth between the client and
server.
* Installation
:PROPERTIES:
:CUSTOM_ID: installation
:END:
Over here we will cover the basic steps to get the server and client
side running.
** Latest release install
:PROPERTIES:
:CUSTOM_ID: latest-release-install
:END:
https://github.com/Akilan1999/p2p-rendering-computation/releases
** Install from Github master branch
:PROPERTIES:
:CUSTOM_ID: install-from-github-master-branch
:END:
*** Install Go lang
:PROPERTIES:
:CUSTOM_ID: install-go-lang
:END:
The entire the implementation of this project is done using Go lang.
Thus, we need go lang to compile to code to a binary file.
[[https://golang.org/doc/install][Instructions to install Go lang]]
*** Install Docker
:PROPERTIES:
:CUSTOM_ID: install-docker
:END:
In this project the choice of virtualization is Docker due to it's wide
usage in the developer community. In the server module we use the Docker
Go API to create and interact with the containers.
[[https://docs.docker.com/get-docker/][Instructions to install docker]]
[[https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker][Instructions
to install docker GPU]]
#+begin_example
// Do ensure that the docker command does not need sudo to run
sudo chmod 666 /var/run/docker.sock
#+end_example
*** Build Project and install project
:PROPERTIES:
:CUSTOM_ID: build-project-and-install-project
:END:
To set up the internal dependencies and build the entire go code into a
single binary
#+begin_example
make
#+end_example
**** For Windows
:PROPERTIES:
:CUSTOM_ID: for-windows
:END:
To set up P2PRC on Windows, simply run this batch file. *Make sure you
are not in admin mode when running this.*
#+begin_example
.\install.bat
#+end_example
*** Add appropriate paths to =.bashrc=
:PROPERTIES:
:CUSTOM_ID: add-appropriate-paths-to-.bashrc
:END:
#+begin_example
export P2PRC=/<PATH>/p2p-rendering-computation
export PATH=/<PATH>/p2p-rendering-computation:${PATH}
#+end_example
*** Test if binary works
:PROPERTIES:
:CUSTOM_ID: test-if-binary-works
:END:
#+begin_example
p2prc --help
#+end_example
**** Output:
:PROPERTIES:
:CUSTOM_ID: output
:END:
#+begin_example
NAME:
p2p-rendering-computation - p2p cli application to create and access VMs in other servers
USAGE:
p2prc [global options] command [command options] [arguments...]
VERSION:
2.0.0
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--Server, -s Starts server (default: false) [$SERVER]
--UpdateServerList, --us Update List of Server available based on servers iptables (default: false) [$UPDATE_SERVER_LIST]
--ListServers, --ls List servers which can render tasks (default: false) [$LIST_SERVERS]
--AddServer value, --as value Adds server IP address to iptables [$ADD_SERVER]
--ViewImages value, --vi value View images available on the server IP address [$VIEW_IMAGES]
--CreateVM value, --touch value Creates Docker container on the selected server [$CREATE_VM]
--ContainerName value, --cn value Specifying the container run on the server side [$CONTAINER_NAME]
--BaseImage value, --bi value Specifying the docker base image to template the dockerfile [$CONTAINER_NAME]
--RemoveVM value, --rm value Stop and Remove Docker container (IP:port) accompanied by container ID via --ID or --id [$REMOVE_VM]
--ID value, --id value Docker Container ID [$ID]
--Ports value, -p value Number of ports to open for the Docker Container [$NUM_PORTS]
--GPU, --gpu Create Docker Containers to access GPU (default: false) [$USE_GPU]
--Specification value, --specs value Specs of the server node [$SPECS]
--SetDefaultConfig, --dc Sets a default configuration file (default: false) [$SET_DEFAULT_CONFIG]
--NetworkInterfaces, --ni Shows the network interface in your computer (default: false) [$NETWORK_INTERFACE]
--ViewPlugins, --vp Shows plugins available to be executed (default: false) [$VIEW_PLUGIN]
--TrackedContainers, --tc View (currently running) containers which have been created from the client side (default: false) [$TRACKED_CONTAINERS]
--ExecutePlugin value, --plugin value Plugin which needs to be executed [$EXECUTE_PLUGIN]
--CreateGroup, --cgroup Creates a new group (default: false) [$CREATE_GROUP]
--Group value, --group value group flag with argument group ID [$GROUP]
--Groups, --groups View all groups (default: false) [$GROUPS]
--RemoveContainerGroup, --rmcgroup Remove specific container in the group (default: false) [$REMOVE_CONTAINER_GROUP]
--RemoveGroup value, --rmgroup value Removes the entire group [$REMOVE_GROUP]
--MAPPort value, --mp value Maps port for a specific port provided as the parameter [$MAPPORT]
--DomainName value, --dn value While mapping ports allows to set a domain name to create a mapping in the proxy server [$DOMAINNAME]
--Generate value, --gen value Generates a new copy of P2PRC which can be modified based on your needs [$GENERATE]
--ModuleName value, --mod value New go project module name [$MODULENAME]
--PullPlugin value, --pp value Pulls plugin from git repos [$PULLPLUGIN]
--RemovePlugin value, --rp value Removes plugin [$REMOVEPLUGIN]
--AddMetaData value, --amd value Adds metadata about the current node in the p2p network which is then propagated through the network [$ADDMETADATA]
--help, -h show help (default: false)
--version, -v print the version (default: false)
#+end_example
--------------
* Using basic commands
:PROPERTIES:
:CUSTOM_ID: using-basic-commands
:END:
*** Start as a server
:PROPERTIES:
:CUSTOM_ID: start-as-a-server
:END:
#+begin_example
p2prc -s
#+end_example
*** View server Specification
:PROPERTIES:
:CUSTOM_ID: view-server-specification
:END:
#+begin_example
p2prc --specs=<ip address>
#+end_example
*** Run container
:PROPERTIES:
:CUSTOM_ID: run-container
:END:
use the =--gpu= if you know the other machine has a gpu.
#+begin_example
p2prc --touch=<server ip address> -p <number of ports> --gpu
#+end_example
*** Remove container
:PROPERTIES:
:CUSTOM_ID: remove-container
:END:
The docker id is present in the output where you create a container
#+begin_example
p2prc --rm=<server ip address> --id=<docker container id>
#+end_example
*** Adding servers to ip table
:PROPERTIES:
:CUSTOM_ID: adding-servers-to-ip-table
:END:
#+begin_example
p2prc --as=<server ip address you want to add>
#+end_example
*** Update ip table
:PROPERTIES:
:CUSTOM_ID: update-ip-table
:END:
#+begin_example
p2prc --us
#+end_example
*** List Servers
:PROPERTIES:
:CUSTOM_ID: list-servers
:END:
#+begin_example
p2prc --ls
#+end_example
*** View Network interfaces
:PROPERTIES:
:CUSTOM_ID: view-network-interfaces
:END:
#+begin_example
p2prc --ni
#+end_example
*** Viewing Containers created Client side
:PROPERTIES:
:CUSTOM_ID: viewing-containers-created-client-side
:END:
#+begin_example
p2prc --tc
#+end_example
*** Running plugin
:PROPERTIES:
:CUSTOM_ID: running-plugin
:END:
#+begin_example
p2prc --plugin <plugin name> --id <container id or group id>
#+end_example
*** Create group
:PROPERTIES:
:CUSTOM_ID: create-group
:END:
#+begin_example
p2prc --cgroup
#+end_example
*** Add container to group
:PROPERTIES:
:CUSTOM_ID: add-container-to-group
:END:
#+begin_example
p2prc --group <group id> --id <container id>
#+end_example
*** View groups
:PROPERTIES:
:CUSTOM_ID: view-groups
:END:
#+begin_example
p2prc --groups
#+end_example
*** View specific group
:PROPERTIES:
:CUSTOM_ID: view-specific-group
:END:
#+begin_example
p2prc --group <group id>
#+end_example
*** Delete container from group
:PROPERTIES:
:CUSTOM_ID: delete-container-from-group
:END:
#+begin_example
p2prc --rmcgroup --group <group id> --id <container id>
#+end_example
*** Delete entire group
:PROPERTIES:
:CUSTOM_ID: delete-entire-group
:END:
#+begin_example
p2prc --rmgroup <group id>
#+end_example
*** Pulling plugin from a remote repo
:PROPERTIES:
:CUSTOM_ID: pulling-plugin-from-a-remote-repo
:END:
#+begin_example
p2prc --pp <repo link>
#+end_example
*** Deleting plugin from the plugin directory
:PROPERTIES:
:CUSTOM_ID: deleting-plugin-from-the-plugin-directory
:END:
#+begin_example
p2prc --rp <plugin name>
#+end_example
*** Added custom metadata about the current node
:PROPERTIES:
:CUSTOM_ID: added-custom-metadata-about-the-current-node
:END:
#+begin_example
p2prc --amd "custom metadata"
#+end_example
*** MapPort and link to domain name
Allows to expose remote ports from a machine in the P2P network.
#+begin_example
p2prc --mp <port no to map> --dn <domain name to link Mapped port against>
#+end_example
**** MapPort in remote machine
This is to ensure ports on remote machines on the P2PRC can be easily opened.
#+begin_example
p2prc --mp <port no to map> --dn <domain name to link Mapped port against> --ra <remote server address>
#+end_example
--------------
* P2P Module Implementation
:PROPERTIES:
:CUSTOM_ID: p2p-module-implementation
:END:
The P2P module is for managing server information within the network.
It maintains and updates the IP table, ensuring accuracy by preventing duplicates and removing
entries for unreachable servers. Furthermore, the module conducts speed tests on the listed servers
to determine upload and download speeds. This valuable information enables users to identify nearby
servers with optimal performance, enhancing their overall network experience.
#+caption: UML diagram of P2P module
[[file:Docs/images/p2pmoduleArch.png]
The peer to peer implementation was built from scratch. This is because
other peer to peer libraries were on the implementation of the
Distributed hash table. At the current moment all those heavy features
are not needed because the objective is to search and list all possible
servers available. The limitation being that to be a part of the network
the user has to know at least 1 server. The advantage of building from
scratch makes the module super light and possibility for custom
functions and structs. The sub topics below will mention the
implementations of each functionality in depth.
** IP Table
:PROPERTIES:
:CUSTOM_ID: ip-table
:END:
The ip table file is a json as the format with a list of servers ip
addresses, latencies, downloads and uploads speeds. The functions
implemented include read file, write file and remove duplicate IP
addresses. The remove duplicate IP address function exists because
sometimes servers IP tables can have the same ip addresses as what the
client has. The path of the IP table json file is received from the
configuration module.
#+begin_src json
{
"ip_address": [
{
"Name": "<hostname of the machine>",
"MachineUsername": "<machine username>",
"IPV4": "<ipv4 address>",
"IPV6": "<ipv6 address (Not used)>",
"Latency": <latency to the server>,
"Download": <download speed (Not used)>,
"Upload": <upload speed (Not used)>,
"ServerPort": "<server port no>",
"BareMetalSSHPort": "<Baremetal ssh port no>",
"NAT": "<boolean representing if the node is behind NAT or not>",
"EscapeImplementation": "<NAT traversal implementation>",
"ProxyServer": "<If the node listed is acting as a proxy server>",
"UnSafeMode": <Unsafe mode if turned on will allow all nodes in the network public keys to be
added to that particular node>",
"PublicKey": "<Public key of that particular node>",
"CustomInformation": "<custom information passed in through all the nodes in the network>"
}
]
}
#+end_src
*** Latency
:PROPERTIES:
:CUSTOM_ID: latency
:END:
The latency is measured in milliseconds. The route /server_info is
called from the server and time it takes to provide a json response is
recorded.
** NAT Traversal
:PROPERTIES:
:CUSTOM_ID: nat-traversal
:END:
P2PRC currently supports TURN for NAT traversal.
** TURN
:PROPERTIES:
:CUSTOM_ID: turn
:END:
The current TURN implementation used is FRP. The TURN server is also
required when a P2PRC node is acting as a Server. The TURN server is
determined based on the Node with the least amount of latency based on
the Nodes available on the IPTable. Once a TURN server is determined
there are 2 actions performed. The first one is =/FRPPort= to the TURN
server to receive a port which is used to generate the external port
from the TURN server. The flow below describes the workflow.
*** Client mode
:PROPERTIES:
:CUSTOM_ID: client-mode
:END:
- Call =/FRPPort=
#+begin_example
http://<turn server ip>:<server port no>/FRPport
#+end_example
- Call the TURN server in the following manner. The following is a
sample code snippet below.
#+begin_src go
import (
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
)
func main() {
serverPort, err := frp.GetFRPServerPort("http://" + <lowestLatencyIpAddress.Ipv4> + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil {
return nil, err
}
// Create 1 second delay to allow FRP server to start
time.Sleep(1 * time.Second)
// Starts FRP as a client with
proxyPort, err := frp.StartFRPClientForServer(<lowestLatencyIpAddress.Ipv4>, serverPort, <the port you want to expose externally>)
if err != nil {
return nil, err
}
}
#+end_src
* Language Bindings
:PROPERTIES:
:CUSTOM_ID: language-bindings
:END:
[[https://en.wikipedia.org/wiki/Language_binding][Language bindings]]
refers to wrappers to bridge 2 programming languages. This is used in
P2PRC to extend calling P2PRC functions in other programming languages.
Currently this is done by generating =.so= and =.h= from the Go
compiler.
** How to build shared object files
:PROPERTIES:
:CUSTOM_ID: how-to-build-shared-object-files
:END:
**** The easier way
:PROPERTIES:
:CUSTOM_ID: the-easier-way
:END:
#+begin_src sh
# Run
make sharedObjects
#+end_src
**** Or the direct way
:PROPERTIES:
:CUSTOM_ID: or-the-direct-way
:END:
#+begin_src sh
# Run
cd Bindings && go build -buildmode=c-shared -o p2prc.so
#+end_src
**** If successfully built:
:PROPERTIES:
:CUSTOM_ID: if-successfully-built
:END:
#+begin_src sh
# Enter into the Bindings directory
cd Bindings
# List files
ls
# Find files
p2prc.h p2prc.so
#+end_src
** Workings under the hood
:PROPERTIES:
:CUSTOM_ID: workings-under-the-hood
:END:
Below are a sample set of commands to open the bindings implementation.
#+begin_example
# run
cd Bindings/
# list files
ls
# search for file
Client.go
#+end_example
*** In Client go
:PROPERTIES:
:CUSTOM_ID: in-client-go
:END:
There a few things to notice which are different from your standard Go
programs:
**** 1. We import "C" which means [[https://pkg.go.dev/cmd/cgo][Cgo]] is required.
:PROPERTIES:
:CUSTOM_ID: we-import-c-which-means-cgo-is-required.
:END:
#+begin_src go
import "C"
#+end_src
**** 2. All functions which are required to be called from other programming languages have comment such as.
:PROPERTIES:
:CUSTOM_ID: all-functions-which-are-required-to-be-called-from-other-programming-languages-have-comment-such-as.
:END:
#+begin_src go
//export <function name>
// ------------ Example ----------------
// The function below allows to externally
// to call the P2PRC function to start containers
// in a specific node in the know list of nodes
// in the p2p network.
// Note: the comment "//export StartContainer".
//export StartContainer
func StartContainer(IP string) (output *C.char) {
container, err := client.StartContainer(IP, 0, false, "", "")
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(container)
}
#+end_src
**** 3. While looking through the file (If 2 files are compared it is pretty trivial to notice a common structure).
:PROPERTIES:
:CUSTOM_ID: while-looking-through-the-file-if-2-files-are-compared-it-is-pretty-trivial-to-notice-a-common-structure.
:END:
#+begin_src go
// --------- Example ------------
//export StartContainer
func StartContainer(IP string) (output *C.char) {
container, err := client.StartContainer(IP, 0, false, "", "")
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(container)
}
//export ViewPlugin
func ViewPlugin() (output *C.char) {
plugins, err := plugin.DetectPlugins()
if err != nil {
return C.CString(err.Error())
}
return ConvertStructToJSONString(plugins)
}
#+end_src
**** It is easy to notice that:
:PROPERTIES:
:CUSTOM_ID: it-is-easy-to-notice-that
:END:
- =ConvertStructToJSONString(<go object>)=: This is a helper function
that convert a go object to JSON string initially and converts it to
=CString=.
- =(output *C.char)=: This is the return type for most of the functions.
**** A Pseudo code to refer to the common function implementation shape could be represented as:
:PROPERTIES:
:CUSTOM_ID: a-pseudo-code-to-refer-to-the-common-function-implementation-shape-could-be-represented-as
:END:
#+begin_example
func <Function name> (output *C.char) {
<response>,<error> := <P2PRC function name>(<parameters if needed>)
if <error> != nil {
return C.CString(<error>.Error())
}
return ConvertStructToJSONString(<response>)
}
#+end_example
** Current languages supported
:PROPERTIES:
:CUSTOM_ID: current-languages-supported
:END:
*** Python
**** Build sample python program
:PROPERTIES:
:CUSTOM_ID: build-sample-python-program
:END:
The easier way
#+begin_src sh
# Run
make python
# Expected ouput
Output is in the Directory Bindings/python/export/
# Run
cd Bindings/python/export/
# list files
ls
# Expected output
SharedObjects/ library.py requirements.txt
#+end_src
Above shows a generated folder which consists of a folder called
"SharedObjects/" which consists of =p2prc.so= and =p2prc.h= files.
=p2prc.py= refers to a sample python script calling P2PRC go functions.
To start an any project to extend P2PRC with python, This generated
folder can copied and created as a new git repo for P2PRC extensions
scripted or used a reference point as proof of concept that P2PRC can be
called from other programming languages.
*** Haskell
P2PRC officially supports Haskell bindings and will further support
project using Haskell to build orchestrators on top of P2PRC.
[[https://p2prc.akilan.io/Docs/haskell][Read more...]]
* Config Implementation
:PROPERTIES:
:CUSTOM_ID: config-implementation
:END:
The configuration module is responsible to store basic information of
absolute paths of files being called in the Go code. In a full-fledged
Cli the configuration file can be found in the directory /etc/ and from
there points to location such as where the IP table file is located. In
the future implementation the config file will have information such as
number of hops and other parameters to tweak and to improve the
effectiveness of the peer to peer network. The configuration module was
implemented using the library Viper. The Viper library automates
features such as searching in default paths to find out if the
configuration file is present. If the configuration file is not present
in the default paths then it auto generates the configuration file. The
configurations file can be in any format. In this project the
configuration file was generated using JSON format.
#+begin_src json
{
"MachineName": "pc-74-120.customer.ask4.lan",
"IPTable": "/Users/akilan/Documents/p2p-rendering-computation/p2p/iptable/ip_table.json",
"DockerContainers": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/",
"DefaultDockerFile": "/Users/akilan/Documents/p2p-rendering-computation/server/docker/containers/docker-ubuntu-sshd/",
"SpeedTestFile": "/Users/akilan/Documents/p2p-rendering-computation/p2p/50.bin",
"IPV6Address": "",
"PluginPath": "/Users/akilan/Documents/p2p-rendering-computation/plugin/deploy",
"TrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/trackcontainers.json",
"ServerPort": "8088",
"GroupTrackContainersPath": "/Users/akilan/Documents/p2p-rendering-computation/client/trackcontainers/grouptrackcontainers.json",
"FRPServerPort": "True",
"BehindNAT": "True",
"CustomConfig": null
}
#+end_src
* Abstractions
:PROPERTIES:
:CUSTOM_ID: abstractions
:END:
The Abstractions package consists of black-boxed functions for P2PRC.
** Functions
:PROPERTIES:
:CUSTOM_ID: functions
:END:
- =Init(<Project name>)=: Initializes P2PRC with all the needed
configurations.
- =Start()=: Starts p2prc as a server and makes it possible to extend by
adding other routes and functionality to P2PRC.
- =MapPort(<port no>)=: On the local machine the port you want to export
to world.
- =StartContainer(<ip address>)=: The machine on the p2p network where
you want to spin up a docker container.
- =RemoveContainer(<ip address>,<container id>)=: Terminate container
based on the IP address and container name.
- =GetSpecs(<ip address>)=: Get specs of a machine on the network based
on the IP address.
- =ViewIPTable()=: View the IP table which about nodes in the network.
- =UpdateIPTable()=: Force update IP table to learn about new nodes
faster.
* NAT Traversal
:PROPERTIES:
:CUSTOM_ID: nat-traversal
:END:
P2PRC currently supports TURN for NAT traversal.
** TURN
:PROPERTIES:
:CUSTOM_ID: turn
:END:
The current TURN implementation used is FRP. The TURN server is also
required when a P2PRC node is acting as a Server. The TURN server is
determined based on the Node with the least amount of latency based on
the Nodes available on the IPTable. Once a TURN server is determined
there are 2 actions performed. The first one is =/FRPPort= to the TURN
server to receive a port which is used to generate the external port
from the TURN server. The flow below describes the workflow.
* Client mode
:PROPERTIES:
:CUSTOM_ID: client-mode
:END:
- Call =/FRPPort=
#+begin_example
http://<turn server ip>:<server port no>/FRPport
#+end_example
- Call the TURN server in the following manner. The following is a
sample code snippet below.
#+begin_src go
import (
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
)
func main() {
serverPort, err := frp.GetFRPServerPort("http://" + <lowestLatencyIpAddress.Ipv4> + ":" + lowestLatencyIpAddress.ServerPort)
if err != nil {
return nil, err
}
// Create 1 second delay to allow FRP server to start
time.Sleep(1 * time.Second)
// Starts FRP as a client with
proxyPort, err := frp.StartFRPClientForServer(<lowestLatencyIpAddress.Ipv4>, serverPort, <the port you want to expose externally>)
if err != nil {
return nil, err
}
}
#+end_src
* Blog posts
** Self host within 5 minutes any program
- Author: [[http://akilan.io/][Akilan Selvacoumar]]
- Date: 28-01-2025
- Video tutorial:
[[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
quickly do a map port and domain name mapping in a single command.
*** 1. Find a program you want to run
Let's try to setup a really easy program (Let's do with Linkwarden
with docker compose :) ). This is under the assumption you have docker
compose installed on your local machine.
**** Let's run Linkwarden using docker compose and P2PRC
[[https://docs.linkwarden.app/self-hosting/installation][Installation instructions]]:
#+BEGIN_SRC
mkdir linkwarden && cd linkwarden
curl -O https://raw.githubusercontent.com/linkwarden/linkwarden/refs/heads/main/docker-compose.yml
curl -L https://raw.githubusercontent.com/linkwarden/linkwarden/refs/heads/main/.env.sample -o ".env"
#+END_SRC
Environment configuration
#+BEGIN_SRC
vim .env
# Change values
NEXTAUTH_URL=https://<DOMAIN NAME>/api/v1/auth
NEXTAUTH_SECRET=VERY_SENSITIVE_SECRET
POSTGRES_PASSWORD=CUSTOM_POSTGRES_PASSWORD
#+END_SRC
Run linkwarden!
#+BEGIN_SRC
docker compose up
#+END_SRC
If setup correctly linkwarden should
be running.
Local link: http://localhost:3000
Time to setup P2PRC
[[https://p2prc.akilan.io/Docs/#build-project-and-install-project][Installation Instructions]]
Run p2prc as a background
#+BEGIN_SRC
p2prc -s &
#+END_SRC
Run map port and domain mapping
#+BEGIN_SRC
p2prc --mp 3000 --dn <DOMAIN NAME>
#+END_SRC
Sample response
#+BEGIN_SRC
{
"IPAddress": "217.76.63.222",
"PortNo": "61582",
"EntireAddress": "217.76.63.222:61582"
}
#+END_SRC
Add DNS entry
#+BEGIN_SRC
A entry 217.76.63.222
#+END_SRC
Your done now just head to the DOMAIN NAME you added.
ex: https://linkwarden.akilan.io
* Ideas for future potencial features
Consists of personal loideas for the future of P2PRC.
At moment only has main contributors writiing to this.
** To support hetrogenous set of Nodes that cannot run P2PRC
This stems from a personal issue I have when doing research
on [[https://github.com/CTSRD-CHERI/cheribsd][CheriBSD]] kernel. For my research I am using the ARM morello
which is a 128bit ARMv8 processor. At the moment Go programs
can cannot compile and run inside the CPU. This means I cannot
run P2PRC at the moment inside the ARM morello to remotely access
it when it's behind NAT using P2PRC. This would indeed be a common
problem when running against various Architectures that do not
support running P2PRC. As you will see soon this also creates
oppurtunity space to scale faster to nodes in a local network
and would introduce a new layer fault tolerance within a local
network nodes.
*** Assumptions:
- I have a Morello board that cannot run P2PRC
- The Morello has a local IP address (ex: 192.168.0.10)
- I have 2 laptops running P2PRC in that local network.
- This means I have 2 ways to access the Morello board: Which is to SSH
into either 2 laptops and then SSH into 192.168.0.10 to gain access
to the board. Wouldn't it be great to automate this whole layer and
as well look into custom tasks into the hetrogenous hardware.
*** Set of interesting possible:
We build a cool set possibilities before and use this to build up the implementation
plan.
- We can use P2PRC access the morello board remotely in a single command.
- We can use the P2PRC protocol to run servers inside the morello board via traversed
node locally which can access that Node.
- Spin servers on node not running P2PRC using the P2PRC standard abstractions.
- Auto-setup P2PRC nodes with just SSH access via potencially a DSL.
- A neat use case for CHERI for instance would be use the architecture to run light
weight hypervisors.
*** Implementation
- To use implementations similar to [[https://linux.die.net/man/1/socat][socat]] to ensure we can bind address of local
nodes to a node running P2PRC and the node running P2PRC can do a local map port.
- We are working on hardening the implementation of the --mp (Map port) to even
map ports to machines which remotely running P2PRC. This means of instance I
can issue a command to the Morello board without the morello board being in
my local network.
- We would want to implement the exsisting P2PRC public key mechanism as well so that
other nodes can access the Morello board who have permission access.
#+CAPTION: Implementation idea (To be improved upon)
[[./Docs/images/P2PRCRemoteNodes.png]]

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,49 @@
{
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:xecarlox94/p2p-rendering-computation?ref=nix";
};
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
];
# TODO: add cabal2nix shell command
# cabal2nix . --shell > ./shell.nix
shellHook = ''
cabal2nix . > ./cabal.nix
'';
};
}
));
}

View File

@@ -29,9 +29,9 @@ type IpAddress struct {
Upload float64 `json:"Upload"`
ServerPort string `json:"ServerPort"`
BareMetalSSHPort string `json:"BareMetalSSHPort"`
NAT string `json:"NAT"`
NAT bool `json:"NAT"`
EscapeImplementation string `json:"EscapeImplementation"`
ProxyServer string `json:"ProxyServer"`
ProxyServer bool `json:"ProxyServer"`
UnSafeMode bool `json:"UnSafeMode"`
PublicKey string `json:"PublicKey"`
CustomInformation string `json:"CustomInformation"`
@@ -42,6 +42,8 @@ type IP struct {
Query string
}
var Test = false
// ReadIpTable Read data from Ip tables from json file
func ReadIpTable() (*IpAddresses, error) {
// Get Path from config
@@ -161,7 +163,7 @@ func (table *IpAddresses) RemoveDuplicates() error {
}
}
if table.IpAddress[i].NAT == "True" && table.IpAddress[i].EscapeImplementation == "None" {
if table.IpAddress[i].NAT && table.IpAddress[i].EscapeImplementation == "None" {
Exists = true
}
@@ -178,6 +180,16 @@ func (table *IpAddresses) RemoveDuplicates() error {
// CurrentPublicIP Get Current Public IP address
func CurrentPublicIP() (string, error) {
// Get configs
Config, err := config.ConfigInit(nil, nil)
if err != nil {
return "", err
}
// If test mode is on then return local address
if Config.Test {
return "0.0.0.0", nil
}
req, err := http.Get("http://ip-api.com/json/")
if err != nil {
return "", err

View File

@@ -95,7 +95,7 @@ func (ip *IpAddresses) SpeedTestUpdatedIPTable() error {
}
// Checks if both the IPV4 addresses are the same or the IPV6 address is not
// an empty string and IPV6 address are the same
if (ip.IpAddress[k].Ipv4 == targets.IpAddress[i].Ipv4 && targets.IpAddress[i].NAT == "True") || (targets.IpAddress[i].Ipv6 != "" && ip.IpAddress[k].Ipv6 == targets.IpAddress[i].Ipv6) {
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) {
Exists = true
break
}

View File

@@ -255,7 +255,7 @@ func Server() (*gin.Engine, error) {
// TODO check if IPV6 or Proxy port is specified
// if not update current entry as proxy address
// with appropriate port on IP Table
if config.BehindNAT == "True" {
if config.BehindNAT {
if err != nil {
return nil, err
}
@@ -267,7 +267,7 @@ func Server() (*gin.Engine, error) {
for i, _ := range table.IpAddress {
// Checks if the ping is the lowest and if the following node is acting as a proxy
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" {
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].NAT != "" {
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && !table.IpAddress[i].NAT {
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
lowestLatencyIpAddress = table.IpAddress[i]
}
@@ -291,8 +291,8 @@ func Server() (*gin.Engine, error) {
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
ProxyIpAddr.ServerPort = proxyPort
ProxyIpAddr.Name = config.MachineName
ProxyIpAddr.NAT = "False"
ProxyIpAddr.ProxyServer = "False"
ProxyIpAddr.NAT = false
ProxyIpAddr.ProxyServer = false
ProxyIpAddr.EscapeImplementation = "FRP"
if config.BareMetal {
@@ -312,11 +312,12 @@ func Server() (*gin.Engine, error) {
if err != nil {
fmt.Println(err)
}
ProxyIpAddr.ServerPort = config.ServerPort
ProxyIpAddr.Name = config.MachineName
ProxyIpAddr.NAT = "False"
ProxyIpAddr.NAT = false
if config.ProxyPort != "" {
ProxyIpAddr.ProxyServer = "True"
ProxyIpAddr.ProxyServer = true
}
ProxyIpAddr.EscapeImplementation = ""
if config.BareMetal {
@@ -425,9 +426,9 @@ func MapPort(port string, domainName string) (string, string, error) {
for i, _ := range table.IpAddress {
// Checks if the ping is the lowest and if the following node is acting as a proxy
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" {
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].NAT != "" {
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && !table.IpAddress[i].NAT {
// 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()
lowestLatencyIpAddress = table.IpAddress[i]
continue
@@ -466,7 +467,7 @@ func MapPort(port string, domainName string) (string, string, error) {
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
ProxyIpAddr.ServerPort = proxyPort
ProxyIpAddr.Name = config.MachineName
ProxyIpAddr.NAT = "False"
ProxyIpAddr.NAT = false
ProxyIpAddr.EscapeImplementation = "FRP"
//ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey)

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.