Compare commits
33 Commits
p2prc-docs
...
add-root-n
| Author | SHA1 | Date | |
|---|---|---|---|
| 2283736cc6 | |||
| 51b253df15 | |||
| b9f5dec9de | |||
| 30b464449c | |||
| ffd711f448 | |||
| 0d01d70c2b | |||
| 6b1edd3d8a | |||
| 5cf1e144aa | |||
|
|
f605e2e06b | ||
| 873caa911c | |||
| 73a470e201 | |||
| 805514edfa | |||
|
|
5e3a4e8b7a | ||
| 5f8407a37f | |||
| a6939ec35e | |||
|
|
c445ac88c4 | ||
| 9075ab5967 | |||
| 125d113ade | |||
| e7e0641f31 | |||
| 05655e2da1 | |||
| ed8d2be205 | |||
|
|
30cd9c1901 | ||
| d9d5ebe475 | |||
| 23abbc8f90 | |||
|
|
5c0bcfd4cf | ||
| 9b255265c4 | |||
| 075d1850f6 | |||
| 38bef975d5 | |||
|
|
5cbc9842b4 | ||
| 4479a79912 | |||
| 88a4e02e30 | |||
| ddd6864741 | |||
|
|
3735ab87e0 |
49
.github/workflows/pages.yml
vendored
49
.github/workflows/pages.yml
vendored
@@ -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
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -43,6 +43,9 @@ p2prc.PublicKeyBareMetal
|
|||||||
# Ignore pem files
|
# Ignore pem files
|
||||||
*.pem
|
*.pem
|
||||||
|
|
||||||
|
# ignore virtual env file
|
||||||
|
venv
|
||||||
|
|
||||||
# Nix and Nix flake files
|
# Nix and Nix flake files
|
||||||
result
|
result
|
||||||
result-*
|
result-*
|
||||||
|
|||||||
@@ -135,11 +135,29 @@ func EscapeFirewall(HostOutsideNATIP string, HostOutsideNATPort string, internal
|
|||||||
|
|
||||||
//export MapPort
|
//export MapPort
|
||||||
func MapPort(Port string, DomainName string, ServerAddress string) *C.char {
|
func MapPort(Port string, DomainName string, ServerAddress string) *C.char {
|
||||||
entireAddress, _, err := abstractions.MapPort(Port, DomainName, ServerAddress)
|
Address, err := abstractions.MapPort(Port, DomainName, ServerAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return C.CString(err.Error())
|
return C.CString(err.Error())
|
||||||
}
|
}
|
||||||
return C.CString(entireAddress)
|
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 ----------------------------------------
|
// --------------------------------- Controlling Server ----------------------------------------
|
||||||
|
|||||||
2
Bindings/Haskell/.mhsi
Normal file
2
Bindings/Haskell/.mhsi
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
exit
|
||||||
|
Exit
|
||||||
@@ -20,19 +20,21 @@ import Error
|
|||||||
import JSON
|
import JSON
|
||||||
( IPAddressTable(..)
|
( IPAddressTable(..)
|
||||||
, MapPortResponse(..)
|
, MapPortResponse(..)
|
||||||
, P2prcConfig
|
, P2PRCConfig
|
||||||
)
|
)
|
||||||
|
|
||||||
import CLI
|
import CLI
|
||||||
( StdInput(..)
|
( StdInput(..)
|
||||||
, CLIOpt(..)
|
, CLIOpt(..)
|
||||||
, eitherErrDecode
|
, eitherErrDecode
|
||||||
, p2PrcCmdName
|
, p2prcCmdName
|
||||||
, eitherExecProcess
|
, eitherExecProcess
|
||||||
, eitherExecProcessParser
|
, eitherExecProcessParser
|
||||||
, spawnProcP2Prc
|
, spawnProcP2PRC
|
||||||
)
|
)
|
||||||
|
|
||||||
|
-- import System.Environment (lookupEnv)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- | Lower level P2PRC Haskell api that exposes basic functionality necessary to joint the network.
|
-- | Lower level P2PRC Haskell api that exposes basic functionality necessary to joint the network.
|
||||||
@@ -41,7 +43,7 @@ data P2PRCapi
|
|||||||
= MkP2PRCapi
|
= MkP2PRCapi
|
||||||
{ startServer :: IOEitherError ProcessHandle
|
{ startServer :: IOEitherError ProcessHandle
|
||||||
-- ^ Start server
|
-- ^ Start server
|
||||||
, execInitConfig :: IOEitherError P2prcConfig
|
-- , execInitConfig :: IOEitherError P2PRCConfig
|
||||||
-- ^ Instantiate server configuration
|
-- ^ Instantiate server configuration
|
||||||
, execListServers :: IOEitherError IPAddressTable
|
, execListServers :: IOEitherError IPAddressTable
|
||||||
-- ^ List servers in network
|
-- ^ List servers in network
|
||||||
@@ -94,14 +96,14 @@ main =
|
|||||||
p2prcAPI :: P2PRCapi
|
p2prcAPI :: P2PRCapi
|
||||||
p2prcAPI =
|
p2prcAPI =
|
||||||
MkP2PRCapi
|
MkP2PRCapi
|
||||||
{ startServer = spawnProcP2Prc p2PrcCmdName [ MkOptAtomic "--s" ]
|
{ startServer = spawnProcP2PRC p2prcCmdName [ MkOptAtomic "--s" ]
|
||||||
|
|
||||||
, execListServers =
|
, execListServers =
|
||||||
execProcP2PrcParser [ MkOptAtomic "--ls" ] MkEmptyStdInput
|
execProcP2PRCParser [ MkOptAtomic "--ls" ] MkEmptyStdInput
|
||||||
|
|
||||||
, execMapPort =
|
, execMapPort =
|
||||||
\ (MkMapPortRequest portNumber domainName) ->
|
\ (MkMapPortRequest portNumber domainName) ->
|
||||||
execProcP2PrcParser
|
execProcP2PRCParser
|
||||||
[ MkOptTuple
|
[ MkOptTuple
|
||||||
( "--mp"
|
( "--mp"
|
||||||
, show portNumber
|
, show portNumber
|
||||||
@@ -113,39 +115,41 @@ p2prcAPI =
|
|||||||
]
|
]
|
||||||
MkEmptyStdInput
|
MkEmptyStdInput
|
||||||
|
|
||||||
, execInitConfig = do
|
-- , execInitConfig = do
|
||||||
|
|
||||||
confInitRes <- execProcP2Prc [ MkOptAtomic "--dc" ] MkEmptyStdInput
|
-- confInitRes <- execProcP2PRC [ MkOptAtomic "--dc" ] MkEmptyStdInput
|
||||||
|
|
||||||
case confInitRes of
|
-- case confInitRes of
|
||||||
(Right _) -> do
|
-- (Right _) -> do
|
||||||
|
|
||||||
-- TODO: get config file name dynamically
|
-- maybeValue <- lookupEnv "P2PRC"
|
||||||
--
|
|
||||||
currDirectory <- getCurrentDirectory
|
|
||||||
|
|
||||||
-- TODO: change values before loading file
|
-- -- TODO: get config file name dynamically
|
||||||
let fname = currDirectory ++ "/config.json" :: FilePath
|
-- --
|
||||||
|
-- currDirectory <- getCurrentDirectory
|
||||||
|
|
||||||
|
-- -- TODO: change values before loading file
|
||||||
|
-- let fname = currDirectory ++ "/config.json" :: FilePath
|
||||||
|
|
||||||
|
|
||||||
-- TODO: read config check if file exists
|
-- -- TODO: read config check if file exists
|
||||||
configContent <- readFile fname
|
-- configContent <- readFile fname
|
||||||
|
|
||||||
pure $ eitherErrDecode configContent
|
-- pure $ eitherErrDecode configContent
|
||||||
|
|
||||||
(Left err) -> pure $ Left err
|
-- (Left err) -> pure $ Left err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
where
|
where
|
||||||
|
|
||||||
execProcP2PrcParser ::
|
execProcP2PRCParser ::
|
||||||
FromJSON a =>
|
FromJSON a =>
|
||||||
[CLIOpt] -> StdInput -> IOEitherError a
|
[CLIOpt] -> StdInput -> IOEitherError a
|
||||||
|
|
||||||
execProcP2PrcParser = eitherExecProcessParser p2PrcCmdName
|
execProcP2PRCParser = eitherExecProcessParser p2prcCmdName
|
||||||
-- TODO: GHC question, why does it scope down instead staying generic
|
-- TODO: GHC question, why does it scope down instead staying generic
|
||||||
|
|
||||||
execProcP2Prc = eitherExecProcess p2PrcCmdName
|
-- execProcP2PRC = eitherExecProcess p2prcCmdName
|
||||||
|
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ optsToCLI = concatMap _optToCLI
|
|||||||
_optToCLI (MkOptTuple (o, v)) = [o, v]
|
_optToCLI (MkOptTuple (o, v)) = [o, v]
|
||||||
|
|
||||||
|
|
||||||
spawnProcP2Prc :: CLICmd -> [CLIOpt] -> IOEitherError ProcessHandle
|
spawnProcP2PRC :: CLICmd -> [CLIOpt] -> IOEitherError ProcessHandle
|
||||||
spawnProcP2Prc cmd opts =
|
spawnProcP2PRC cmd opts =
|
||||||
do
|
do
|
||||||
let prc = proc cmd $ optsToCLI opts
|
let prc = proc cmd $ optsToCLI opts
|
||||||
|
|
||||||
@@ -115,6 +115,6 @@ eitherErrorDecode esa =
|
|||||||
|
|
||||||
-- assumes the program is ran inside the haskell module in p2prc's repo
|
-- assumes the program is ran inside the haskell module in p2prc's repo
|
||||||
-- assumes that last path segment is "haskell" and that p2prc binary's name is "p2p-rendering-computation"
|
-- assumes that last path segment is "haskell" and that p2prc binary's name is "p2p-rendering-computation"
|
||||||
p2PrcCmdName :: String
|
p2prcCmdName :: String
|
||||||
p2PrcCmdName = "p2p-rendering-computation"
|
p2prcCmdName = "p2prc"
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ runP2PRC
|
|||||||
|
|
||||||
( MkP2PRCapi
|
( MkP2PRCapi
|
||||||
{ startServer = startServer
|
{ startServer = startServer
|
||||||
, execInitConfig = execInitConfig
|
-- , execInitConfig = execInitConfig
|
||||||
, execListServers = execListServers
|
, execListServers = execListServers
|
||||||
, execMapPort = execMapPort
|
, execMapPort = execMapPort
|
||||||
}
|
}
|
||||||
@@ -105,12 +105,12 @@ runP2PRC
|
|||||||
let
|
let
|
||||||
|
|
||||||
|
|
||||||
configValue <- execInitConfig
|
-- configValue <- execInitConfig
|
||||||
|
|
||||||
-- TODO: get name of host server from config json
|
-- TODO: get name of host server from config json
|
||||||
|
|
||||||
print configValue
|
-- print configValue
|
||||||
putStrLn "\n\n\n"
|
-- putStrLn "\n\n\n"
|
||||||
|
|
||||||
eitherStartProcessHandle <- startServer
|
eitherStartProcessHandle <- startServer
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
module JSON
|
module JSON
|
||||||
( P2prcConfig(..)
|
( P2PRCConfig(..)
|
||||||
, IPAddressTable(..)
|
, IPAddressTable(..)
|
||||||
, IPAddress(..)
|
, IPAddress(..)
|
||||||
, ServerInfo(..)
|
, ServerInfo(..)
|
||||||
@@ -38,11 +38,11 @@ instance FromJSON MapPortResponse where
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
{-# WARNING P2prcConfig "This type is unstable at the moment due to the P2PRC's library error handling bug. For more information visit: https://github.com/Akilan1999/p2p-rendering-computation/issues/114#issuecomment-2474737015" #-}
|
{-# WARNING P2PRCConfig "This type is unstable at the moment due to the P2PRC's library error handling bug. For more information visit: https://github.com/Akilan1999/p2p-rendering-computation/issues/114#issuecomment-2474737015" #-}
|
||||||
|
|
||||||
-- | This represents the server configuration that defines its attributes and behaviours in the network, as well as, the location of the runtime persistence artifacts.
|
-- | This represents the server configuration that defines its attributes and behaviours in the network, as well as, the location of the runtime persistence artifacts.
|
||||||
newtype P2prcConfig
|
newtype P2PRCConfig
|
||||||
= MkP2prConfig
|
= MkP2PRCConfig
|
||||||
{ machineName :: String -- ^ Machine Name
|
{ machineName :: String -- ^ Machine Name
|
||||||
} deriving Show
|
} deriving Show
|
||||||
|
|
||||||
@@ -96,13 +96,13 @@ newtype P2prcConfig
|
|||||||
-- to have a dedicated port field
|
-- to have a dedicated port field
|
||||||
|
|
||||||
|
|
||||||
instance FromJSON P2prcConfig where
|
instance FromJSON P2PRCConfig where
|
||||||
parseJSON (Object o) = do
|
parseJSON (Object o) = do
|
||||||
|
|
||||||
machineName <- o .: "MachineName"
|
machineName <- o .: "MachineName"
|
||||||
|
|
||||||
pure
|
pure
|
||||||
$ MkP2prConfig
|
$ MkP2PRCConfig
|
||||||
{ machineName=machineName
|
{ machineName=machineName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ module P2PRC
|
|||||||
-- ** Interface data types
|
-- ** Interface data types
|
||||||
-- | This section gives an overview on the runtime and host machine interfaces.
|
-- | This section gives an overview on the runtime and host machine interfaces.
|
||||||
, P2PRCapi(..)
|
, P2PRCapi(..)
|
||||||
, P2prcConfig(..)
|
, P2PRCConfig(..)
|
||||||
, MapPortRequest(..)
|
, MapPortRequest(..)
|
||||||
, MapPortResponse(..)
|
, MapPortResponse(..)
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ import JSON
|
|||||||
, ServerInfo(..)
|
, ServerInfo(..)
|
||||||
, IPAddress(..)
|
, IPAddress(..)
|
||||||
, MapPortResponse(..)
|
, MapPortResponse(..)
|
||||||
, P2prcConfig(..)
|
, P2PRCConfig(..)
|
||||||
)
|
)
|
||||||
|
|
||||||
import API
|
import API
|
||||||
|
|||||||
BIN
Bindings/python/.DS_Store
vendored
BIN
Bindings/python/.DS_Store
vendored
Binary file not shown.
129
Bindings/python/library.py
Normal file
129
Bindings/python/library.py
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import ctypes
|
||||||
|
from ctypes import Structure, c_char_p, c_int, cdll
|
||||||
|
from dataclasses import dataclass, astuple
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
from typing import List
|
||||||
|
import subprocess
|
||||||
|
import uuid
|
||||||
|
import dacite
|
||||||
|
import os
|
||||||
|
import sqlalchemy
|
||||||
|
import dataclasses
|
||||||
|
from typing import Union
|
||||||
|
import schedule
|
||||||
|
import threading
|
||||||
|
import requests
|
||||||
|
|
||||||
|
p2prc = ctypes.CDLL("SharedObjects/p2prc.so")
|
||||||
|
|
||||||
|
p2prc.Init("")
|
||||||
|
|
||||||
|
# Start running schedule
|
||||||
|
schedule.run_pending()
|
||||||
|
|
||||||
|
# # Create Sqlite database to track processes
|
||||||
|
# engine=sqlalchemy.create_engine(f'sqlite:///homeserver.db')
|
||||||
|
|
||||||
|
# Global variable
|
||||||
|
# A global variable will be populated on runtime.
|
||||||
|
# It is read from P2PRC directly or from a local
|
||||||
|
# database.
|
||||||
|
|
||||||
|
# Node information
|
||||||
|
# Generated using: https://jsonformatter.org/json-to-python
|
||||||
|
@dataclass
|
||||||
|
class Node:
|
||||||
|
Name: str
|
||||||
|
MachineUsername: str
|
||||||
|
IPV4: str
|
||||||
|
IPV6: str
|
||||||
|
Latency: int
|
||||||
|
Download: int
|
||||||
|
Upload: int
|
||||||
|
ServerPort: str
|
||||||
|
BareMetalSSHPort: str
|
||||||
|
NAT: bool
|
||||||
|
EscapeImplementation: str
|
||||||
|
ProxyServer: bool
|
||||||
|
UnSafeMode: bool
|
||||||
|
PublicKey: str
|
||||||
|
CustomInformation: str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class IPAddress:
|
||||||
|
ip_address: List[Node]
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# ----------------------------- Helper functions -----------------------------
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def StartServer():
|
||||||
|
# Starting P2PRC as a server mode
|
||||||
|
p2prc.Server()
|
||||||
|
|
||||||
|
# Class to create string to pass as string function
|
||||||
|
# parameter to shared object file
|
||||||
|
class go_string(Structure):
|
||||||
|
_fields_ = [
|
||||||
|
("p", c_char_p),
|
||||||
|
("n", c_int)]
|
||||||
|
|
||||||
|
# Ensuring local port can escape NAT and responds
|
||||||
|
# with the public ip and port no.
|
||||||
|
# If the domain name is specified then the public IP
|
||||||
|
# can be used as an A name entry.
|
||||||
|
def P2PRCMapPort(port="",domainname="",serveraddress=""):
|
||||||
|
port = go_string(c_char_p(port.encode('utf-8')), len(port))
|
||||||
|
domainname = go_string(c_char_p(domainname.encode('utf-8')), len(domainname))
|
||||||
|
serveraddress = go_string(c_char_p(serveraddress.encode('utf-8')), len(serveraddress))
|
||||||
|
|
||||||
|
# Defining the response type of the GoLang function
|
||||||
|
# function
|
||||||
|
p2prc.MapPort.restype = c_char_p
|
||||||
|
# Calling the Go function
|
||||||
|
address = p2prc.MapPort(port,domainname,serveraddress)
|
||||||
|
res = str(address).strip("b'")
|
||||||
|
return res
|
||||||
|
|
||||||
|
# Lists all avaliable nodes in the network
|
||||||
|
def ListNodes():
|
||||||
|
# View IP Table information
|
||||||
|
p2prc.ViewIPTable.restype = c_char_p
|
||||||
|
ipTable = p2prc.ViewIPTable()
|
||||||
|
# View IP Table as
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import ctypes
|
|
||||||
|
|
||||||
p2prc = ctypes.CDLL("SharedOBjects/p2prc.so")
|
|
||||||
|
|
||||||
p2prc.Init("")
|
|
||||||
|
|
||||||
def StartServer():
|
|
||||||
# Starting P2PRC as a server mode
|
|
||||||
p2prc.Server()
|
|
||||||
for _ in iter(int, 1):
|
|
||||||
pass
|
|
||||||
4
Bindings/python/requirements.txt
Normal file
4
Bindings/python/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
dacite
|
||||||
|
schedule
|
||||||
|
sqlalchemy
|
||||||
|
requests
|
||||||
14
Bindings/python/test.py
Normal file
14
Bindings/python/test.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
from library import *
|
||||||
|
|
||||||
|
|
||||||
|
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")
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
* Contributing
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: contributing
|
|
||||||
:END:
|
|
||||||
When contributing to this repository, please first discuss the change
|
|
||||||
you wish to make via issue, email, or any other method with the owners
|
|
||||||
of this repository before making a change.
|
|
||||||
|
|
||||||
Please note we have a code of conduct, please follow it in all your
|
|
||||||
interactions with the project.
|
|
||||||
|
|
||||||
** Pull Request Process
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: pull-request-process
|
|
||||||
:END:
|
|
||||||
1. Ensure any install or build dependencies are removed before the end
|
|
||||||
of the layer when doing a build.
|
|
||||||
2. Update the appropriate docs before stating the changes you did.
|
|
||||||
3. You may merge the Pull Request in once you have the approval of
|
|
||||||
CODEOWNER, or if you do not have permission to do that, you may
|
|
||||||
request the second reviewer to merge it for you.
|
|
||||||
|
|
||||||
** Code of conduct
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: code-of-conduct
|
|
||||||
:END:
|
|
||||||
All projects(including mailing lists) at HWTechClub is required to
|
|
||||||
follow [[https://lunduke.com/pages/codeofconduct/][The Lunduke Code of
|
|
||||||
Conduct]].
|
|
||||||
|
|
||||||
*** The Lunduke Code of Conduct
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: the-lunduke-code-of-conduct
|
|
||||||
:END:
|
|
||||||
|
|
||||||
#+begin_quote
|
|
||||||
**** "Be Excellent to Each Other."
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: be-excellent-to-each-other.
|
|
||||||
:END:
|
|
||||||
#+end_quote
|
|
||||||
|
|
||||||
***** FAQ
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: faq
|
|
||||||
:END:
|
|
||||||
*Q*: Wait. That's it?
|
|
||||||
|
|
||||||
A: Yup.
|
|
||||||
|
|
||||||
*Q*: But... but... it's only 5 words!
|
|
||||||
|
|
||||||
A: It is? Cool!
|
|
||||||
|
|
||||||
*Q*: Isn't that too short to be a viable Code of Conduct?
|
|
||||||
|
|
||||||
A: Nah.
|
|
||||||
|
|
||||||
*Q*: It's too vague! How would you enforce this?!?
|
|
||||||
|
|
||||||
A: By being excellent to each other.
|
|
||||||
|
|
||||||
*Q*: What if someone violates this Code of Conduct?
|
|
||||||
|
|
||||||
A: I trust you to figure it out.
|
|
||||||
|
|
||||||
*Q*: What if someone talks about politics I disagree with?!?!!?
|
|
||||||
|
|
||||||
A: I know a guy who votes for Papa Smurf in every Presidential election.
|
|
||||||
He's a pretty cool dude.
|
|
||||||
|
|
||||||
*Q*: I'm super angry about something! And a person likes the thing
|
|
||||||
making me angry! What do I do?
|
|
||||||
|
|
||||||
A: I dunno. Try /hugs/?
|
|
||||||
|
|
||||||
*Q*: Are virtual hugs (such as /"hugs"/ and animated .GIFs of teddy
|
|
||||||
bears hugging) excellent?
|
|
||||||
|
|
||||||
A: Most excellent.
|
|
||||||
|
|
||||||
*Q*: Huh. Seems so simple!
|
|
||||||
|
|
||||||
A: I know, right?
|
|
||||||
|
|
||||||
*Q*: I like you!
|
|
||||||
|
|
||||||
A: I like you, too!
|
|
||||||
|
|
||||||
/The Lunduke Code of Conduct is free for you to use however you like./
|
|
||||||
|
|
||||||
*Source*: [[https://lunduke.com/pages/codeofconduct/][The Lunduke Code
|
|
||||||
of Conduct]]
|
|
||||||
BIN
Docs/.DS_Store
vendored
BIN
Docs/.DS_Store
vendored
Binary file not shown.
1
Docs/.gitignore
vendored
1
Docs/.gitignore
vendored
@@ -13,7 +13,6 @@
|
|||||||
*.elc
|
*.elc
|
||||||
*.fn
|
*.fn
|
||||||
*.fns
|
*.fns
|
||||||
*.html
|
|
||||||
*.info
|
*.info
|
||||||
*.ky
|
*.ky
|
||||||
*.kys
|
*.kys
|
||||||
|
|||||||
BIN
Docs/Colored-On-Light-Image.png
Normal file
BIN
Docs/Colored-On-Light-Image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 276 KiB |
1268
Docs/index.html
Normal file
1268
Docs/index.html
Normal file
File diff suppressed because it is too large
Load Diff
920
Docs/index.org
Normal file
920
Docs/index.org
Normal file
@@ -0,0 +1,920 @@
|
|||||||
|
#+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
|
||||||
|
[[./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:
|
||||||
|
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
|
||||||
|
|
||||||
|
--------------
|
||||||
|
|
||||||
|
*** 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
|
||||||
|
: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:./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:
|
||||||
|
#+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
|
||||||
|
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)
|
||||||
|
[[./images/P2PRCRemoteNodes.png]]
|
||||||
1
Docs/run-docs.sh
Normal file
1
Docs/run-docs.sh
Normal file
@@ -0,0 +1 @@
|
|||||||
|
go run staticServer.go &
|
||||||
28
Docs/staticServer.go
Normal file
28
Docs/staticServer.go
Normal 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))
|
||||||
|
}
|
||||||
@@ -23,3 +23,7 @@ h4,h5,h6{
|
|||||||
color: #b96c29;
|
color: #b96c29;
|
||||||
font-weight:300;
|
font-weight:300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.video {
|
||||||
|
box-shadow: 10px 10px 25px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -47,11 +47,27 @@ Networking details are completely abstracted, enabling users to focus on develop
|
|||||||
### Flexible Task Distribution
|
### Flexible Task Distribution
|
||||||
Users acting as clients retain full control over how tasks are batched and assigned to nodes, creating endless possibilities for optimising performance based on specific use cases.
|
Users acting as clients retain full control over how tasks are batched and assigned to nodes, creating endless possibilities for optimising performance based on specific use cases.
|
||||||
|
|
||||||
|
## Setup with Nix
|
||||||
|
- Ensure you have the nix package manager installed.
|
||||||
|
- Add the following to your .bashrc file.
|
||||||
|
```bash
|
||||||
|
alias p2prc='env P2PRC=<path you want the configs to exist in> nix run github:akilan1999/p2p-rendering-computation --'
|
||||||
|
```
|
||||||
|
- Check if it's successful
|
||||||
|
```bash
|
||||||
|
p2prc -h
|
||||||
|
```
|
||||||
|
Read more on command usage: https://p2prc.akilan.io/Docs/#using-basic-commands
|
||||||
|
|
||||||
## Latest tutorial
|
## Latest tutorial
|
||||||
[](https://www.youtube.com/watch?v=OMwCpedu5cs")
|
[](https://www.youtube.com/watch?v=OMwCpedu5cs")
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
### We have documented to our best effort the basics of p2prc: [Link](https://p2prc.akilan.io/Docs/)
|
||||||
|
|
||||||
<!-- ## Table of contents in the current README -->
|
<!-- ## Table of contents in the current README -->
|
||||||
<!-- 1. [Introduction](#Introduction)
|
<!-- 1. [Introduction](#Introduction)
|
||||||
2. [Installation](#extend-your-application-with-p2prc)
|
2. [Installation](#extend-your-application-with-p2prc)
|
||||||
@@ -98,7 +114,7 @@ This project aims to create a peer to peer (p2p) network, where a user can use t
|
|||||||
|
|
||||||
<!-- <br> -->
|
<!-- <br> -->
|
||||||
|
|
||||||
## Extend your application with P2PRC
|
<!-- ## Extend your application with P2PRC
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@@ -127,7 +143,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
``` -->
|
||||||
|
|
||||||
<!-- ### Export once this is added export P2PRC as environment paths
|
<!-- ### Export once this is added export P2PRC as environment paths
|
||||||
```
|
```
|
||||||
@@ -190,4 +206,4 @@ The programming language used for this project was Golang. The reason Go lang wa
|
|||||||
As we are working on the open source project p2prc (i.e p2p network designed for computation).If you are interested in participating as a contributor
|
As we are working on the open source project p2prc (i.e p2p network designed for computation).If you are interested in participating as a contributor
|
||||||
or just providing feedback on new features to build or even just curious about new features added to the project do file an Issue or send an email to me@akilan.io.
|
or just providing feedback on new features to build or even just curious about new features added to the project do file an Issue or send an email to me@akilan.io.
|
||||||
|
|
||||||
[](https://github.com/Gaurav-Gosain)
|
<!-- [](https://github.com/Gaurav-Gosain) -->
|
||||||
|
|||||||
252
README.md.org
252
README.md.org
@@ -1,252 +0,0 @@
|
|||||||
#+begin_quote
|
|
||||||
[!TIP] Haskell bindings supported!:
|
|
||||||
[[https://p2prc.akilan.io/Docs/haskell/P2PRC.html][Bindings
|
|
||||||
documentaton]]
|
|
||||||
|
|
||||||
#+end_quote
|
|
||||||
|
|
||||||
#+begin_quote
|
|
||||||
[!NOTE] Fixing documentation to latest changes. If you have any
|
|
||||||
questions setting up P2PRC either
|
|
||||||
[[https://github.com/Akilan1999/p2p-rendering-computation/issues/new/choose][create
|
|
||||||
an issue]] or send me an email (me AT akilan dot io). Currently HEAD is
|
|
||||||
always intended to stay on a working state. It is recommended to always
|
|
||||||
use HEAD in your go.mod file.
|
|
||||||
|
|
||||||
#+end_quote
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<h1 align="center">
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
</h1>
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<!-- seperator -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<!-- The main aim of this project was to create a custom peer to peer network. The user acting as the
|
|
||||||
client has total flexibility on how to batch the tasks and the user acting as the server has complete
|
|
||||||
flexibility on tracking the container's usages and killing the containers at any point of time. -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<!-- The objective is to allow users to self host servers in easier
|
|
||||||
and abstracted manner. The main aim of this project was to create a custom peer to peer network for distributed computing. The user acting as the client has total flexibility on how to batch the tasks to any of nodes in networks. These nodes can anywhere from personal
|
|
||||||
computers behind NAT to custom hardware for running custom workload. The aim to provide
|
|
||||||
access to Heterogeneous set of nodes as a singular global list and abstract away the networking details giving the user focus on designing a custom orchestrator based
|
|
||||||
on the requirements of a user. -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
This project aims to simplify self-hosting servers and streamline the
|
|
||||||
creation of distributed systems. The primary focus is to enable users to
|
|
||||||
design custom peer-to-peer networks for distributed computing, offering
|
|
||||||
full flexibility and control while abstracting away the complexities of
|
|
||||||
networking.
|
|
||||||
|
|
||||||
** Key Features
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: key-features
|
|
||||||
:END:
|
|
||||||
Simplified Self-Hosting Empower users to easily host nodes, whether on
|
|
||||||
personal computers behind NAT, custom hardware, or cloud-based
|
|
||||||
infrastructure.
|
|
||||||
|
|
||||||
*** Custom Peer-to-Peer Networks
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: custom-peer-to-peer-networks
|
|
||||||
:END:
|
|
||||||
Build a decentralised network tailored to user requirements, enabling
|
|
||||||
distributed task execution without the need for in-depth networking
|
|
||||||
knowledge.
|
|
||||||
|
|
||||||
*** Heterogeneous Node Support
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: heterogeneous-node-support
|
|
||||||
:END:
|
|
||||||
Harness a diverse array of nodes from personal computers to specialised
|
|
||||||
hardware---seamlessly integrated into a global node list.
|
|
||||||
|
|
||||||
*** Abstracted Networking Layer
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: abstracted-networking-layer
|
|
||||||
:END:
|
|
||||||
Networking details are completely abstracted, enabling users to focus on
|
|
||||||
developing bespoke task orchestration systems. No more manual
|
|
||||||
configuration of IPs, ports, or connection logic.
|
|
||||||
|
|
||||||
*** Flexible Task Distribution
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: flexible-task-distribution
|
|
||||||
:END:
|
|
||||||
Users acting as clients retain full control over how tasks are batched
|
|
||||||
and assigned to nodes, creating endless possibilities for optimising
|
|
||||||
performance based on specific use cases.
|
|
||||||
|
|
||||||
** Latest tutorial
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: latest-tutorial
|
|
||||||
:END:
|
|
||||||
[[https://www.youtube.com/watch?v=OMwCpedu5cs%22][[[https://i.ytimg.com/vi/OMwCpedu5cs/hqdefault.jpg]]]]
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<!-- ## Table of contents in the current README -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<!-- 1. [Introduction](#Introduction)
|
|
||||||
2. [Installation](#extend-your-application-with-p2prc)
|
|
||||||
3. [Design Architecture](#Design-Architecture)
|
|
||||||
4. [Implementation](#Implementation)
|
|
||||||
5. [Find out more](#Find-out-more) -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<!-- # Table of contents in the Docs folder
|
|
||||||
1. [Introduction](Docs/Introduction.md)
|
|
||||||
2. [Installation](Docs/Installation.md)
|
|
||||||
3. [Abstractions](Docs/Abstractions.md)
|
|
||||||
3. [Design Architecture](DesignArchtectureIntro.md)
|
|
||||||
1. [Client Module](ClientArchitecture.md)
|
|
||||||
2. [P2P Module](P2PArchitecture.md)
|
|
||||||
3. [Server Module](ServerArchitecture.md)
|
|
||||||
4. [Implementation](Docs/Implementation.md)
|
|
||||||
1. [Client Module](Docs/ClientImplementation.md)
|
|
||||||
2. [P2P Module](Docs/P2PImplementation.md)
|
|
||||||
3. [Server Module](Docs/ServerImplementation.md)
|
|
||||||
4. [Config Module](Docs/ConfigImplementation.md)
|
|
||||||
5. [Cli Module](Docs/CliImplementation.md)
|
|
||||||
6. [Plugin Module](Docs/PluginImplementation.md)
|
|
||||||
7. [Language bindings](Docs/Bindings.md)
|
|
||||||
8. [Domain name mappings](Docs/Bindings.md)
|
|
||||||
5. Language bindings
|
|
||||||
1. [Haskell](Docs/haskell/)
|
|
||||||
5. [Problems](https://github.com/Akilan1999/p2p-rendering-computation/issues) -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<!--
|
|
||||||
## Introduction
|
|
||||||
This project aims to create a peer to peer (p2p) network, where a user can use the p2p network to act as a client (i.e sending tasks) or the server (i.e executing the tasks). A prototype application will be developed, which comes bundled with a p2p module and possible to execute docker containers or virtual environments across selected nodes.
|
|
||||||
|
|
||||||
### Objectives
|
|
||||||
- Background review on peer to peer network, virtual environments, decentralized rendering tools and tools to batch any sort of tasks.
|
|
||||||
- Creating p2p network
|
|
||||||
- Server to create a containerised environment
|
|
||||||
- The client node to run tasks on Server containerised node -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<!-- [Read more on the introduction](Docs/Introduction.md) -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<!-- <br> -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
** Extend your application with P2PRC
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: extend-your-application-with-p2prc
|
|
||||||
:END:
|
|
||||||
#+begin_src go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/abstractions"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
_, err := abstractions.Init(nil)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// start p2prc
|
|
||||||
_, err = abstractions.Start()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run server till termination
|
|
||||||
for {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
#+begin_html
|
|
||||||
<!-- ### Export once this is added export P2PRC as environment paths
|
|
||||||
```
|
|
||||||
export P2PRC=<PROJECT PATH>
|
|
||||||
export PATH=<PROJECT PATH>:${PATH}
|
|
||||||
```
|
|
||||||
[Read more](Docs/Abstractions.md) ...
|
|
||||||
|
|
||||||
## Installation from source
|
|
||||||
1. Ensure the Go compiler is installed
|
|
||||||
```
|
|
||||||
go version
|
|
||||||
```
|
|
||||||
3. Ensure docker is installed (Should run without sudo)
|
|
||||||
```
|
|
||||||
docker ps
|
|
||||||
```
|
|
||||||
3. Clone this repository
|
|
||||||
```
|
|
||||||
git clone https://github.com/Akilan1999/p2p-rendering-computation
|
|
||||||
```
|
|
||||||
4. Install and build the project
|
|
||||||
```
|
|
||||||
make install
|
|
||||||
```
|
|
||||||
- If you look closely you will get outputs such as:
|
|
||||||
```
|
|
||||||
// Add them to your .bashrc file
|
|
||||||
export P2PRC=/<path>/p2p-rendering-computation
|
|
||||||
export PATH=/<path>/p2p-rendering-computation:${PATH}
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Test if it works
|
|
||||||
```
|
|
||||||
p2prc -h
|
|
||||||
```
|
|
||||||
or
|
|
||||||
```
|
|
||||||
./p2prc -h
|
|
||||||
```
|
|
||||||
[Read more on the installation and usage](Docs/Installation.md)
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## Design Architecture
|
|
||||||
The design architecture was inspired and based on the linux kernel design. The project is segmented into various modules. Each module is responsible for certain tasks in the project. The modules are highly dependent on each other hence the entire codebase can be considered as a huge monolithic chuck which acts as its own library
|
|
||||||
|
|
||||||
[Read more on the Design Architecture](Docs/DesignArchtectureIntro.md)
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## Implementation
|
|
||||||
The programming language used for this project was Golang. The reason Go lang was chosen was because it is a compiled language. The entire codebase is just a single binary file. When distributing to other linux distributing the only requirement would be the binary file to run the code. It is easy to write independant modules and be monolithic at the sametime using Go. Using Go.mod makes it very easy to handle external libraries and modularise code. The go.mod name for the project is git.sr.ht/~akilan1999/p2p-rendering-computation.
|
|
||||||
|
|
||||||
[Read more on the Implementation](Docs/Implementation.md)
|
|
||||||
|
|
||||||
<br> -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
** Find out more
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: find-out-more
|
|
||||||
:END:
|
|
||||||
As we are working on the open source project p2prc (i.e p2p network
|
|
||||||
designed for computation).If you are interested in participating as a
|
|
||||||
contributor or just providing feedback on new features to build or even
|
|
||||||
just curious about new features added to the project do file an Issue or
|
|
||||||
send an email to me@akilan.io.
|
|
||||||
|
|
||||||
[[https://github.com/Gaurav-Gosain][[[https://api.star-history.com/svg?repos=Akilan1999/p2p-rendering-computation&type=Date]]]]
|
|
||||||
@@ -52,8 +52,8 @@ func Start() (*gin.Engine, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MapPort Creates a reverse proxy connection and maps the appropriate port
|
// MapPort Creates a reverse proxy connection and maps the appropriate port
|
||||||
func MapPort(port string, domainName string, serverAddress string) (entireAddress string, mapPort string, err error) {
|
func MapPort(port string, domainName string, serverAddress string) (response *client.ResponseMAPPort, err error) {
|
||||||
entireAddress, mapPort, err = server.MapPort(port, domainName, serverAddress)
|
response, err = client.MAPPort(port, domainName, serverAddress)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,3 +86,24 @@ func ViewIPTable() (table *p2p.IpAddresses, err error) {
|
|||||||
func UpdateIPTable() (err error) {
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,12 +6,19 @@ mkdir Bindings/python/export
|
|||||||
# Creating SharedObjects directory for python
|
# Creating SharedObjects directory for python
|
||||||
mkdir Bindings/python/export/SharedObjects
|
mkdir Bindings/python/export/SharedObjects
|
||||||
|
|
||||||
|
# Builds p2prc.h and p2prc.so file
|
||||||
|
# as apart of Go FFI to interacted
|
||||||
|
# with later on.
|
||||||
sh build-bindings.sh
|
sh build-bindings.sh
|
||||||
|
|
||||||
|
# Copy the shared object files as well to ensure
|
||||||
|
# that python can interact with the latest snapshot
|
||||||
|
# of P2PRC
|
||||||
cp Bindings/p2prc.h Bindings/python/export/SharedObjects/
|
cp Bindings/p2prc.h Bindings/python/export/SharedObjects/
|
||||||
cp Bindings/p2prc.so Bindings/python/export/SharedObjects/
|
cp Bindings/p2prc.so Bindings/python/export/SharedObjects/
|
||||||
|
|
||||||
cp Bindings/python/p2prc.py Bindings/python/export/
|
# Copy python library and tests as export as well
|
||||||
|
cp Bindings/python/* Bindings/python/export/
|
||||||
|
|
||||||
echo "Output is in the Directory Bindings/python/export/"
|
echo "Output is in the Directory Bindings/python/export/"
|
||||||
|
|
||||||
|
|||||||
@@ -3,21 +3,30 @@ package client
|
|||||||
import (
|
import (
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/config"
|
"github.com/Akilan1999/p2p-rendering-computation/config"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResponseMAPPort struct {
|
type ResponseMAPPort struct {
|
||||||
IPAddress string
|
IPAddress string
|
||||||
|
PortNo string
|
||||||
|
EntireAddress string
|
||||||
}
|
}
|
||||||
|
|
||||||
func MAPPort(port string, domainName string) (*ResponseMAPPort, error) {
|
func MAPPort(port string, domainName string, ServerAddress string) (*ResponseMAPPort, error) {
|
||||||
Config, err := config.ConfigInit(nil, nil)
|
Config, err := config.ConfigInit(nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
URL := "http://0.0.0.0:" + Config.ServerPort
|
||||||
|
|
||||||
|
if ServerAddress != "" {
|
||||||
|
URL = "http://" + ServerAddress
|
||||||
|
}
|
||||||
|
|
||||||
//if version == "version 6" {
|
//if version == "version 6" {
|
||||||
URL := "http://0.0.0.0:" + Config.ServerPort + "/MAPPort?port=" + port + "&domain_name=" + domainName
|
URL = URL + "/MAPPort?port=" + port + "&domain_name=" + domainName
|
||||||
//} else {
|
//} else {
|
||||||
// URL = "http://" + IP + ":" + serverPort + "/server_info"
|
// URL = "http://" + IP + ":" + serverPort + "/server_info"
|
||||||
//}
|
//}
|
||||||
@@ -32,8 +41,15 @@ func MAPPort(port string, domainName string) (*ResponseMAPPort, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
host, Exposedport, err := net.SplitHostPort(string(byteValue))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var response ResponseMAPPort
|
var response ResponseMAPPort
|
||||||
response.IPAddress = string(byteValue)
|
response.IPAddress = host
|
||||||
|
response.PortNo = Exposedport
|
||||||
|
response.EntireAddress = string(byteValue)
|
||||||
|
|
||||||
return &response, nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
|
|||||||
130
cmd/action.go
130
cmd/action.go
@@ -2,6 +2,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/Akilan1999/p2p-rendering-computation/abstractions"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/client"
|
"github.com/Akilan1999/p2p-rendering-computation/client"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
|
"github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/config/generate"
|
"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
|
// Displays all images available on the server side
|
||||||
if ViewImages != "" {
|
if ViewImages != "" {
|
||||||
imageRes, err := client.ViewContainers(ViewImages)
|
imageRes, err := client.ViewContainers(ViewImages)
|
||||||
|
standardOutput(err, imageRes)
|
||||||
if err != nil {
|
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
client.PrettyPrint(imageRes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function called to stop and remove server from Docker
|
// Function called to stop and remove server from Docker
|
||||||
@@ -100,9 +97,7 @@ var CliAction = func(ctx *cli.Context) error {
|
|||||||
fmt.Println("provide container ID via --ID or --id")
|
fmt.Println("provide container ID via --ID or --id")
|
||||||
} else {
|
} else {
|
||||||
err := client.RemoveContianer(RemoveVM, ID)
|
err := client.RemoveContianer(RemoveVM, ID)
|
||||||
if err != nil {
|
standardOutput(err, nil)
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,58 +114,40 @@ var CliAction = func(ctx *cli.Context) error {
|
|||||||
// Calls function to do Api call to start the container on the server side
|
// Calls function to do Api call to start the container on the server side
|
||||||
imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName, BaseImage)
|
imageRes, err := client.StartContainer(CreateVM, PortsInt, GPU, ContainerName, BaseImage)
|
||||||
|
|
||||||
if err != nil {
|
standardOutput(err, imageRes)
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
client.PrettyPrint(imageRes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Call if specs flag is called
|
//Call if specs flag is called
|
||||||
if Specs != "" {
|
if Specs != "" {
|
||||||
specs, err := client.GetSpecs(Specs)
|
specs, err := client.GetSpecs(Specs)
|
||||||
if err != nil {
|
standardOutput(err, specs)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pretty print
|
|
||||||
client.PrettyPrint(specs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sets default paths to the config file
|
//Sets default paths to the config file
|
||||||
if SetDefaultConfig {
|
if SetDefaultConfig {
|
||||||
_, err := generate.SetDefaults("P2PRC", false, nil, false)
|
_, err := generate.SetDefaults("P2PRC", false, nil, false)
|
||||||
if err != nil {
|
standardOutput(err, nil)
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//If the network interface flag is called
|
//If the network interface flag is called
|
||||||
// Then all the network interfaces are displayed
|
// Then all the network interfaces are displayed
|
||||||
if NetworkInterface {
|
if NetworkInterface {
|
||||||
err := p2p.ViewNetworkInterface()
|
err := p2p.ViewNetworkInterface()
|
||||||
if err != nil {
|
standardOutput(err, nil)
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the view plugin flag is called then display all
|
// If the view plugin flag is called then display all
|
||||||
// plugins available
|
// plugins available
|
||||||
if ViewPlugin {
|
if ViewPlugin {
|
||||||
plugins, err := plugin.DetectPlugins()
|
plugins, err := plugin.DetectPlugins()
|
||||||
if err != nil {
|
standardOutput(err, plugins)
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
client.PrettyPrint(plugins)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the flag Tracked Container is called or the flag
|
// If the flag Tracked Container is called or the flag
|
||||||
// --tc
|
// --tc
|
||||||
if TrackedContainers {
|
if TrackedContainers {
|
||||||
err, trackedContainers := client.ViewTrackedContainers()
|
err, trackedContainers := client.ViewTrackedContainers()
|
||||||
if err != nil {
|
standardOutput(err, trackedContainers)
|
||||||
fmt.Print(err)
|
|
||||||
}
|
|
||||||
client.PrettyPrint(trackedContainers)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Executing plugin when the plugin flag is called
|
//Executing plugin when the plugin flag is called
|
||||||
@@ -179,14 +156,11 @@ var CliAction = func(ctx *cli.Context) error {
|
|||||||
// To execute plugin requires the container ID or group ID provided when being executed
|
// To execute plugin requires the container ID or group ID provided when being executed
|
||||||
if ID != "" {
|
if ID != "" {
|
||||||
err := plugin.CheckRunPlugin(ExecutePlugin, ID)
|
err := plugin.CheckRunPlugin(ExecutePlugin, ID)
|
||||||
if err != nil {
|
standardOutput(err, nil)
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
fmt.Println("Success")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Println("provide container ID via --ID or --id")
|
|
||||||
}
|
}
|
||||||
|
//else {
|
||||||
|
// fmt.Println("provide container ID via --ID or --id")
|
||||||
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,10 +168,7 @@ var CliAction = func(ctx *cli.Context) error {
|
|||||||
// Creates new group and outputs JSON file
|
// Creates new group and outputs JSON file
|
||||||
if CreateGroup {
|
if CreateGroup {
|
||||||
group, err := client.CreateGroup()
|
group, err := client.CreateGroup()
|
||||||
if err != nil {
|
standardOutput(err, group)
|
||||||
return err
|
|
||||||
}
|
|
||||||
client.PrettyPrint(group)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actions to be performed when the
|
// Actions to be performed when the
|
||||||
@@ -208,26 +179,14 @@ var CliAction = func(ctx *cli.Context) error {
|
|||||||
// --rmcgroup --id <contianer id>
|
// --rmcgroup --id <contianer id>
|
||||||
if RemoveContainerGroup && ID != "" {
|
if RemoveContainerGroup && ID != "" {
|
||||||
group, err := client.RemoveContainerGroup(ID, Group)
|
group, err := client.RemoveContainerGroup(ID, Group)
|
||||||
if err != nil {
|
standardOutput(err, group)
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
client.PrettyPrint(group)
|
|
||||||
}
|
|
||||||
} else if ID != "" { // Add container to group based on group ID provided
|
} else if ID != "" { // Add container to group based on group ID provided
|
||||||
// --id <Container ID>
|
// --id <Container ID>
|
||||||
group, err := client.AddContainerToGroup(ID, Group)
|
group, err := client.AddContainerToGroup(ID, Group)
|
||||||
if err != nil {
|
standardOutput(err, group)
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
client.PrettyPrint(group)
|
|
||||||
}
|
|
||||||
} else { // View all information about current group
|
} else { // View all information about current group
|
||||||
group, err := client.GetGroup(Group)
|
group, err := client.GetGroup(Group)
|
||||||
if err != nil {
|
standardOutput(err, group)
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
client.PrettyPrint(group)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,63 +195,52 @@ var CliAction = func(ctx *cli.Context) error {
|
|||||||
// --rmgroup
|
// --rmgroup
|
||||||
if RemoveGroup != "" {
|
if RemoveGroup != "" {
|
||||||
err := client.RemoveGroup(RemoveGroup)
|
err := client.RemoveGroup(RemoveGroup)
|
||||||
if err != nil {
|
standardOutput(err, nil)
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
fmt.Println("Group Removed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute Function to view all groups
|
// Execute Function to view all groups
|
||||||
if Groups {
|
if Groups {
|
||||||
groups, err := client.ReadGroup()
|
groups, err := client.ReadGroup()
|
||||||
if err != nil {
|
standardOutput(err, groups)
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
client.PrettyPrint(groups)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------
|
//--------------------------------
|
||||||
|
|
||||||
if PullPlugin != "" {
|
if PullPlugin != "" {
|
||||||
err := plugin.DownloadPlugin(PullPlugin)
|
err := plugin.DownloadPlugin(PullPlugin)
|
||||||
if err != nil {
|
standardOutput(err, nil)
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
fmt.Println("Success")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if RemovePlugin != "" {
|
if RemovePlugin != "" {
|
||||||
err := plugin.DeletePlugin(RemovePlugin)
|
err := plugin.DeletePlugin(RemovePlugin)
|
||||||
if err != nil {
|
standardOutput(err, nil)
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
fmt.Println("Success")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if AddMetaData != "" {
|
if AddMetaData != "" {
|
||||||
err := clientIPTable.AddCustomInformationToIPTable(AddMetaData)
|
err := clientIPTable.AddCustomInformationToIPTable(AddMetaData)
|
||||||
if err != nil {
|
standardOutput(err, nil)
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
fmt.Println("Success")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if MAPPort != "" {
|
if MAPPort != "" {
|
||||||
address, err := client.MAPPort(MAPPort, DomainName)
|
address, err := client.MAPPort(MAPPort, DomainName, RemoteAddress)
|
||||||
if err != nil {
|
standardOutput(err, address)
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
client.PrettyPrint(address)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Action called to add root node to network
|
||||||
|
if AddRootNode && IP != "" && Ports != "" {
|
||||||
|
err := abstractions.AddRootNode(IP, Ports)
|
||||||
|
standardOutput(err, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func standardOutput(err error, i interface{}) {
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
} else if i == nil {
|
||||||
|
fmt.Println("Success")
|
||||||
|
} else {
|
||||||
|
client.PrettyPrint(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
25
cmd/flags.go
25
cmd/flags.go
@@ -30,6 +30,7 @@ var (
|
|||||||
RemoveContainerGroup bool
|
RemoveContainerGroup bool
|
||||||
RemoveGroup string
|
RemoveGroup string
|
||||||
MAPPort string
|
MAPPort string
|
||||||
|
RemoteAddress string
|
||||||
DomainName string
|
DomainName string
|
||||||
//FRPProxy bool
|
//FRPProxy bool
|
||||||
// Generate only allowed in dev release
|
// Generate only allowed in dev release
|
||||||
@@ -40,10 +41,11 @@ var (
|
|||||||
PullPlugin string
|
PullPlugin string
|
||||||
RemovePlugin string
|
RemovePlugin string
|
||||||
AddMetaData string
|
AddMetaData string
|
||||||
|
AddRootNode bool
|
||||||
|
IP string
|
||||||
)
|
)
|
||||||
|
|
||||||
var AppConfigFlags = []cli.Flag{
|
var AppConfigFlags = []cli.Flag{
|
||||||
// Deprecated to be implemented using GRPC
|
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "Server",
|
Name: "Server",
|
||||||
Aliases: []string{"s"},
|
Aliases: []string{"s"},
|
||||||
@@ -213,6 +215,13 @@ var AppConfigFlags = []cli.Flag{
|
|||||||
EnvVars: []string{"MAPPORT"},
|
EnvVars: []string{"MAPPORT"},
|
||||||
Destination: &MAPPort,
|
Destination: &MAPPort,
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "RemoteAddress",
|
||||||
|
Aliases: []string{"ra"},
|
||||||
|
Usage: "Parameter for Map port for a remote address",
|
||||||
|
EnvVars: []string{"REMOTEADDRESS"},
|
||||||
|
Destination: &RemoteAddress,
|
||||||
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "DomainName",
|
Name: "DomainName",
|
||||||
Aliases: []string{"dn"},
|
Aliases: []string{"dn"},
|
||||||
@@ -265,4 +274,18 @@ var AppConfigFlags = []cli.Flag{
|
|||||||
EnvVars: []string{"ADDMETADATA"},
|
EnvVars: []string{"ADDMETADATA"},
|
||||||
Destination: &AddMetaData,
|
Destination: &AddMetaData,
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "AddRootNode",
|
||||||
|
Aliases: []string{"arn"},
|
||||||
|
Usage: "Adds initial root node to talk to",
|
||||||
|
EnvVars: []string{"ADDROOTNODE"},
|
||||||
|
Destination: &AddRootNode,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "IPAddress",
|
||||||
|
Aliases: []string{"ip"},
|
||||||
|
Usage: "IP address",
|
||||||
|
EnvVars: []string{"IP"},
|
||||||
|
Destination: &IP,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ type Config struct {
|
|||||||
ServerPort string
|
ServerPort string
|
||||||
ProxyPort string
|
ProxyPort string
|
||||||
GroupTrackContainersPath string
|
GroupTrackContainersPath string
|
||||||
FRPServerPort string
|
FRPServerPort bool
|
||||||
BehindNAT string
|
BehindNAT bool
|
||||||
IPTableKey string
|
IPTableKey string
|
||||||
PublicKeyFile string
|
PublicKeyFile string
|
||||||
PrivateKeyFile string
|
PrivateKeyFile string
|
||||||
|
|||||||
@@ -78,9 +78,9 @@ func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, No
|
|||||||
Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json"
|
Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json"
|
||||||
Defaults.ServerPort = "8088"
|
Defaults.ServerPort = "8088"
|
||||||
Defaults.ProxyPort = ""
|
Defaults.ProxyPort = ""
|
||||||
Defaults.FRPServerPort = "True"
|
Defaults.FRPServerPort = true
|
||||||
Defaults.CustomConfig = CustomConfig
|
Defaults.CustomConfig = CustomConfig
|
||||||
Defaults.BehindNAT = "True"
|
Defaults.BehindNAT = true
|
||||||
Defaults.DockerRunLogs = "/tmp/"
|
Defaults.DockerRunLogs = "/tmp/"
|
||||||
// Generate a random key to be added to IPTable
|
// Generate a random key to be added to IPTable
|
||||||
Defaults.IPTableKey = String(12)
|
Defaults.IPTableKey = String(12)
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ func GenerateIPTableFile(rootNodes []p2p.IpAddress) (err error) {
|
|||||||
if len(rootNodes) <= 0 {
|
if len(rootNodes) <= 0 {
|
||||||
rootnode.Name = "Node1"
|
rootnode.Name = "Node1"
|
||||||
rootnode.ServerPort = "8078"
|
rootnode.ServerPort = "8078"
|
||||||
rootnode.NAT = "False"
|
rootnode.NAT = false
|
||||||
rootnode.Ipv4 = "217.76.63.222"
|
rootnode.Ipv4 = "217.76.63.222"
|
||||||
rootnode.ProxyServer = "True"
|
rootnode.ProxyServer = true
|
||||||
|
|
||||||
rootnodes.IpAddress = append(rootnodes.IpAddress, rootnode)
|
rootnodes.IpAddress = append(rootnodes.IpAddress, rootnode)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
11
go.mod
11
go.mod
@@ -11,7 +11,7 @@ require (
|
|||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/lithammer/shortuuid v3.0.0+incompatible
|
github.com/lithammer/shortuuid v3.0.0+incompatible
|
||||||
github.com/otiai10/copy v1.6.0
|
github.com/otiai10/copy v1.6.0
|
||||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
|
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
|
||||||
github.com/shirou/gopsutil/v3 v3.22.10
|
github.com/shirou/gopsutil/v3 v3.22.10
|
||||||
github.com/urfave/cli/v2 v2.3.0
|
github.com/urfave/cli/v2 v2.3.0
|
||||||
gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3
|
gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3
|
||||||
@@ -31,7 +31,7 @@ require (
|
|||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
github.com/containerd/containerd v1.5.0-beta.1 // indirect
|
github.com/containerd/containerd v1.5.0-beta.1 // indirect
|
||||||
github.com/coreos/go-oidc v2.2.1+incompatible // indirect
|
github.com/coreos/go-oidc v2.2.1+incompatible // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||||
github.com/docker/go-connections v0.4.0 // indirect
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
github.com/docker/go-units v0.4.0 // indirect
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
@@ -76,10 +76,9 @@ require (
|
|||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.37.0 // indirect
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
github.com/prometheus/procfs v0.8.0 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sergi/go-diff v1.1.0 // indirect
|
github.com/sergi/go-diff v1.1.0 // indirect
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/sirupsen/logrus v1.7.0 // indirect
|
|
||||||
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
|
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
|
||||||
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
|
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
|
||||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
@@ -91,7 +90,7 @@ require (
|
|||||||
gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect
|
gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect
|
||||||
golang.org/x/net v0.10.0 // indirect
|
golang.org/x/net v0.10.0 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
|
||||||
golang.org/x/sys v0.15.0 // indirect
|
golang.org/x/sys v0.29.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
|||||||
19
go.sum
19
go.sum
@@ -183,8 +183,9 @@ github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+
|
|||||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
@@ -548,8 +549,8 @@ github.com/otiai10/mint v1.3.2 h1:VYWnrP5fXmz1MXvjuUvcBrXSjGE6xjON+axB/UrpO3E=
|
|||||||
github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
|
github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
|
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
|
||||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
||||||
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
||||||
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
@@ -611,8 +612,9 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
|||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||||
@@ -620,7 +622,6 @@ github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
|||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/shirou/gopsutil/v3 v3.22.10 h1:4KMHdfBRYXGF9skjDWiL4RA2N+E8dRdodU/bOZpPoVg=
|
github.com/shirou/gopsutil/v3 v3.22.10 h1:4KMHdfBRYXGF9skjDWiL4RA2N+E8dRdodU/bOZpPoVg=
|
||||||
github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk=
|
github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
@@ -628,8 +629,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
|||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
@@ -917,8 +919,9 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||||
|
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||||
|
|||||||
@@ -3,16 +3,18 @@
|
|||||||
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="https://fniessen.github.io/org-html-themes/src/readtheorg_theme/css/search.css"/>
|
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="https://fniessen.github.io/org-html-themes/src/readtheorg_theme/css/search.css"/>
|
||||||
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style.css"/>
|
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="style.css"/>
|
||||||
|
|
||||||
|
#+attr_html: :width 300px :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
|
* Introduction
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:CUSTOM_ID: chapter1-introduction
|
:CUSTOM_ID: chapter1-introduction
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
** Abstract
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: abstract
|
|
||||||
:END:
|
|
||||||
This project focuses on creating a framework for running heavy computational tasks that a regular
|
This project focuses on creating a framework for running heavy computational tasks that a regular
|
||||||
computer cannot handle easily. These tasks may include graphically demanding video games, rendering
|
computer cannot handle easily. These tasks may include graphically demanding video games, rendering
|
||||||
3D animations, and performing complex protein folding simulations. The major focus of this project
|
3D animations, and performing complex protein folding simulations. The major focus of this project
|
||||||
@@ -93,7 +95,7 @@ To set up the internal dependencies and build the entire go code into a
|
|||||||
single binary
|
single binary
|
||||||
|
|
||||||
#+begin_example
|
#+begin_example
|
||||||
make install
|
make
|
||||||
#+end_example
|
#+end_example
|
||||||
|
|
||||||
**** For Windows
|
**** For Windows
|
||||||
@@ -116,17 +118,6 @@ export P2PRC=/<PATH>/p2p-rendering-computation
|
|||||||
export PATH=/<PATH>/p2p-rendering-computation:${PATH}
|
export PATH=/<PATH>/p2p-rendering-computation:${PATH}
|
||||||
#+end_example
|
#+end_example
|
||||||
|
|
||||||
*** Set up configuration file
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: set-up-configuration-file
|
|
||||||
:END:
|
|
||||||
#+begin_example
|
|
||||||
make configfile
|
|
||||||
#+end_example
|
|
||||||
|
|
||||||
Open the config file =config.json= and add the IPv6 address if you have
|
|
||||||
one.
|
|
||||||
|
|
||||||
*** Test if binary works
|
*** Test if binary works
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:CUSTOM_ID: test-if-binary-works
|
:CUSTOM_ID: test-if-binary-works
|
||||||
@@ -351,9 +342,15 @@ p2prc --amd "custom metadata"
|
|||||||
#+end_example
|
#+end_example
|
||||||
|
|
||||||
*** MapPort and link to domain name
|
*** MapPort and link to domain name
|
||||||
|
Allows to expose remote ports from a machine in the P2P network.
|
||||||
#+begin_example
|
#+begin_example
|
||||||
p2prc --mp <port no to map> --dn <domain name to link Mapped port against>
|
p2prc --mp <port no to map> --dn <domain name to link Mapped port against>
|
||||||
#+end_example
|
#+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
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@@ -368,7 +365,7 @@ to determine upload and download speeds. This valuable information enables users
|
|||||||
servers with optimal performance, enhancing their overall network experience.
|
servers with optimal performance, enhancing their overall network experience.
|
||||||
|
|
||||||
#+caption: UML diagram of P2P module
|
#+caption: UML diagram of P2P module
|
||||||
[[file:images/p2pmoduleArch.png]]
|
[[file:Docs/images/p2pmoduleArch.png]
|
||||||
|
|
||||||
The peer to peer implementation was built from scratch. This is because
|
The peer to peer implementation was built from scratch. This is because
|
||||||
other peer to peer libraries were on the implementation of the
|
other peer to peer libraries were on the implementation of the
|
||||||
@@ -628,9 +625,9 @@ func <Function name> (output *C.char) {
|
|||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:CUSTOM_ID: current-languages-supported
|
:CUSTOM_ID: current-languages-supported
|
||||||
:END:
|
:END:
|
||||||
- Python
|
*** Python
|
||||||
|
|
||||||
*** Build sample python program
|
**** Build sample python program
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:CUSTOM_ID: build-sample-python-program
|
:CUSTOM_ID: build-sample-python-program
|
||||||
:END:
|
:END:
|
||||||
@@ -646,7 +643,7 @@ cd Bindings/python/export/
|
|||||||
# list files
|
# list files
|
||||||
ls
|
ls
|
||||||
# Expected output
|
# Expected output
|
||||||
SharedObjects/ p2prc.py
|
SharedObjects/ library.py requirements.txt
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
Above shows a generated folder which consists of a folder called
|
Above shows a generated folder which consists of a folder called
|
||||||
@@ -657,6 +654,11 @@ 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
|
scripted or used a reference point as proof of concept that P2PRC can be
|
||||||
called from other programming languages.
|
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
|
* Config Implementation
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
@@ -775,6 +777,88 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* 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
|
* Ideas for future potencial features
|
||||||
Consists of personal loideas for the future of P2PRC.
|
Consists of personal loideas for the future of P2PRC.
|
||||||
@@ -822,4 +906,4 @@ network nodes.
|
|||||||
other nodes can access the Morello board who have permission access.
|
other nodes can access the Morello board who have permission access.
|
||||||
|
|
||||||
#+CAPTION: Implementation idea (To be improved upon)
|
#+CAPTION: Implementation idea (To be improved upon)
|
||||||
[[./images/P2PRCRemoteNodes.png]]
|
[[./Docs/images/P2PRCRemoteNodes.png]]
|
||||||
6
main.go
6
main.go
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// VERSION specifies the version of the platform
|
// VERSION specifies the version of the platform
|
||||||
var VERSION = "2.0.0"
|
var VERSION = "3.0.0"
|
||||||
var mode string
|
var mode string
|
||||||
|
|
||||||
// Varaibles if mode is client
|
// Varaibles if mode is client
|
||||||
@@ -34,10 +34,6 @@ func getFireSignalsChannel() chan os.Signal {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func exit() {
|
|
||||||
syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "p2p-rendering-computation"
|
app.Name = "p2p-rendering-computation"
|
||||||
|
|||||||
40
main.md.org
40
main.md.org
@@ -1,40 +0,0 @@
|
|||||||
#+begin_html
|
|
||||||
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
|
|
||||||
#+end_html
|
|
||||||
|
|
||||||
* p2p-rendering-computation
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: p2p-rendering-computation
|
|
||||||
:END:
|
|
||||||
#+begin_src go
|
|
||||||
import "github.com/Akilan1999/p2p-rendering-computation"
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
** Index
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: index
|
|
||||||
:END:
|
|
||||||
- [[#variables][Variables]]
|
|
||||||
|
|
||||||
** Variables
|
|
||||||
:PROPERTIES:
|
|
||||||
:CUSTOM_ID: variables
|
|
||||||
:END:
|
|
||||||
|
|
||||||
#+begin_src go
|
|
||||||
var List_servers, Ip_table bool
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
Varaibles if mode is client
|
|
||||||
|
|
||||||
#+begin_src go
|
|
||||||
var OS, Pull_location, Run_script string
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
VERSION specifies the version of the platform
|
|
||||||
|
|
||||||
#+begin_src go
|
|
||||||
var VERSION = "2.0.0"
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
Generated by [[https://github.com/princjef/gomarkdoc][gomarkdoc]]
|
|
||||||
@@ -29,9 +29,9 @@ type IpAddress struct {
|
|||||||
Upload float64 `json:"Upload"`
|
Upload float64 `json:"Upload"`
|
||||||
ServerPort string `json:"ServerPort"`
|
ServerPort string `json:"ServerPort"`
|
||||||
BareMetalSSHPort string `json:"BareMetalSSHPort"`
|
BareMetalSSHPort string `json:"BareMetalSSHPort"`
|
||||||
NAT string `json:"NAT"`
|
NAT bool `json:"NAT"`
|
||||||
EscapeImplementation string `json:"EscapeImplementation"`
|
EscapeImplementation string `json:"EscapeImplementation"`
|
||||||
ProxyServer string `json:"ProxyServer"`
|
ProxyServer bool `json:"ProxyServer"`
|
||||||
UnSafeMode bool `json:"UnSafeMode"`
|
UnSafeMode bool `json:"UnSafeMode"`
|
||||||
PublicKey string `json:"PublicKey"`
|
PublicKey string `json:"PublicKey"`
|
||||||
CustomInformation string `json:"CustomInformation"`
|
CustomInformation string `json:"CustomInformation"`
|
||||||
@@ -161,7 +161,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
|
Exists = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ func (ip *IpAddresses) SpeedTestUpdatedIPTable() error {
|
|||||||
}
|
}
|
||||||
// Checks if both the IPV4 addresses are the same or the IPV6 address is not
|
// Checks if both the IPV4 addresses are the same or the IPV6 address is not
|
||||||
// an empty string and IPV6 address are the same
|
// 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
|
Exists = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ import (
|
|||||||
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
|
"github.com/Akilan1999/p2p-rendering-computation/p2p/frp"
|
||||||
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
|
"github.com/Akilan1999/p2p-rendering-computation/server/docker"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os/user"
|
"os/user"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -195,7 +193,7 @@ func Server() (*gin.Engine, error) {
|
|||||||
r.GET("/MAPPort", func(c *gin.Context) {
|
r.GET("/MAPPort", func(c *gin.Context) {
|
||||||
Ports := c.DefaultQuery("port", "0")
|
Ports := c.DefaultQuery("port", "0")
|
||||||
DomainName := c.DefaultQuery("domain_name", "")
|
DomainName := c.DefaultQuery("domain_name", "")
|
||||||
url, _, err := MapPort(Ports, DomainName, "")
|
url, _, err := MapPort(Ports, DomainName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||||
}
|
}
|
||||||
@@ -257,7 +255,7 @@ func Server() (*gin.Engine, error) {
|
|||||||
// TODO check if IPV6 or Proxy port is specified
|
// TODO check if IPV6 or Proxy port is specified
|
||||||
// if not update current entry as proxy address
|
// if not update current entry as proxy address
|
||||||
// with appropriate port on IP Table
|
// with appropriate port on IP Table
|
||||||
if config.BehindNAT == "True" {
|
if config.BehindNAT {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -269,7 +267,7 @@ func Server() (*gin.Engine, error) {
|
|||||||
for i, _ := range table.IpAddress {
|
for i, _ := range table.IpAddress {
|
||||||
// Checks if the ping is the lowest and if the following node is acting as a proxy
|
// Checks if the ping is the lowest and if the following node is acting as a proxy
|
||||||
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" {
|
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" {
|
||||||
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].NAT != "" {
|
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && !table.IpAddress[i].NAT {
|
||||||
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
|
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
|
||||||
lowestLatencyIpAddress = table.IpAddress[i]
|
lowestLatencyIpAddress = table.IpAddress[i]
|
||||||
}
|
}
|
||||||
@@ -293,12 +291,12 @@ func Server() (*gin.Engine, error) {
|
|||||||
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
|
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
|
||||||
ProxyIpAddr.ServerPort = proxyPort
|
ProxyIpAddr.ServerPort = proxyPort
|
||||||
ProxyIpAddr.Name = config.MachineName
|
ProxyIpAddr.Name = config.MachineName
|
||||||
ProxyIpAddr.NAT = "False"
|
ProxyIpAddr.NAT = false
|
||||||
ProxyIpAddr.ProxyServer = "False"
|
ProxyIpAddr.ProxyServer = false
|
||||||
ProxyIpAddr.EscapeImplementation = "FRP"
|
ProxyIpAddr.EscapeImplementation = "FRP"
|
||||||
|
|
||||||
if config.BareMetal {
|
if config.BareMetal {
|
||||||
_, SSHPort, err := MapPort("22", "", "")
|
_, SSHPort, err := MapPort("22", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -316,9 +314,9 @@ func Server() (*gin.Engine, error) {
|
|||||||
}
|
}
|
||||||
ProxyIpAddr.ServerPort = config.ServerPort
|
ProxyIpAddr.ServerPort = config.ServerPort
|
||||||
ProxyIpAddr.Name = config.MachineName
|
ProxyIpAddr.Name = config.MachineName
|
||||||
ProxyIpAddr.NAT = "False"
|
ProxyIpAddr.NAT = false
|
||||||
if config.ProxyPort != "" {
|
if config.ProxyPort != "" {
|
||||||
ProxyIpAddr.ProxyServer = "True"
|
ProxyIpAddr.ProxyServer = true
|
||||||
}
|
}
|
||||||
ProxyIpAddr.EscapeImplementation = ""
|
ProxyIpAddr.EscapeImplementation = ""
|
||||||
if config.BareMetal {
|
if config.BareMetal {
|
||||||
@@ -375,33 +373,33 @@ func Server() (*gin.Engine, error) {
|
|||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func MapPort(port string, domainName string, serverAddress string) (string, string, error) {
|
func MapPort(port string, domainName string) (string, string, error) {
|
||||||
|
|
||||||
// if server address is provided to do call RESTAPI to remotely open port.
|
// if server address is provided to do call RESTAPI to remotely open port.
|
||||||
if serverAddress != "" {
|
//if serverAddress != "" {
|
||||||
requestURL := fmt.Sprintf("http://%v/MAPPort?port=%v&domain_name=%v", serverAddress, port, domainName)
|
// requestURL := fmt.Sprintf("http://%v/MAPPort?port=%v&domain_name=%v", serverAddress, port, domainName)
|
||||||
req, err := http.NewRequest(http.MethodGet, requestURL, nil)
|
// req, err := http.NewRequest(http.MethodGet, requestURL, nil)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return "", "", err
|
// return "", "", err
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
res, err := http.DefaultClient.Do(req)
|
// res, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return "", "", err
|
// return "", "", err
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
resBody, err := io.ReadAll(res.Body)
|
// resBody, err := io.ReadAll(res.Body)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return "", "", err
|
// return "", "", err
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
_, Exposedport, err := net.SplitHostPort(string(resBody))
|
// _, Exposedport, err := net.SplitHostPort(string(resBody))
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return "", "", err
|
// return "", "", err
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return string(resBody), Exposedport, nil
|
// return string(resBody), Exposedport, nil
|
||||||
}
|
//}
|
||||||
|
|
||||||
//Get Server port based on the config file
|
//Get Server port based on the config file
|
||||||
config, err := config.ConfigInit(nil, nil)
|
config, err := config.ConfigInit(nil, nil)
|
||||||
@@ -427,9 +425,9 @@ func MapPort(port string, domainName string, serverAddress string) (string, stri
|
|||||||
for i, _ := range table.IpAddress {
|
for i, _ := range table.IpAddress {
|
||||||
// Checks if the ping is the lowest and if the following node is acting as a proxy
|
// Checks if the ping is the lowest and if the following node is acting as a proxy
|
||||||
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" {
|
//if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].ProxyPort != "" {
|
||||||
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && table.IpAddress[i].NAT != "" {
|
if table.IpAddress[i].Latency.Milliseconds() < lowestLatency && !table.IpAddress[i].NAT {
|
||||||
// Filter based on nodes with proxy enabled
|
// Filter based on nodes with proxy enabled
|
||||||
if domainName != "" && table.IpAddress[i].ProxyServer == "True" {
|
if domainName != "" && table.IpAddress[i].ProxyServer {
|
||||||
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
|
lowestLatency = table.IpAddress[i].Latency.Milliseconds()
|
||||||
lowestLatencyIpAddress = table.IpAddress[i]
|
lowestLatencyIpAddress = table.IpAddress[i]
|
||||||
continue
|
continue
|
||||||
@@ -468,7 +466,7 @@ func MapPort(port string, domainName string, serverAddress string) (string, stri
|
|||||||
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
|
ProxyIpAddr.Ipv4 = lowestLatencyIpAddress.Ipv4
|
||||||
ProxyIpAddr.ServerPort = proxyPort
|
ProxyIpAddr.ServerPort = proxyPort
|
||||||
ProxyIpAddr.Name = config.MachineName
|
ProxyIpAddr.Name = config.MachineName
|
||||||
ProxyIpAddr.NAT = "False"
|
ProxyIpAddr.NAT = false
|
||||||
ProxyIpAddr.EscapeImplementation = "FRP"
|
ProxyIpAddr.EscapeImplementation = "FRP"
|
||||||
|
|
||||||
//ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey)
|
//ProxyIpAddr.CustomInformationKey = p2p.GenerateHashSHA256(config.IPTableKey)
|
||||||
|
|||||||
32
style.css
32
style.css
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user