6 Commits

Author SHA1 Message Date
5f8407a37f added comment 2025-04-24 23:28:19 +01:00
a6939ec35e added python function call add custom information 2025-04-24 23:15:02 +01:00
Akilan Selvacoumar
c445ac88c4 Merge pull request #124 from Akilan1999/python-bindings
Python bindings (Base function calls)
2025-04-24 22:17:02 +01:00
9075ab5967 added python bindings 2025-04-24 15:51:47 +01:00
125d113ade added base python bindings 2025-04-07 20:25:25 +01:00
e7e0641f31 removed syscall kill 2025-04-07 18:52:18 +01:00
15 changed files with 273 additions and 126 deletions

BIN
.DS_Store vendored

Binary file not shown.

3
.gitignore vendored
View File

@@ -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-*

View File

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

2
Bindings/Haskell/.mhsi Normal file
View File

@@ -0,0 +1,2 @@
exit
Exit

View File

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

View File

@@ -0,0 +1 @@
z

Binary file not shown.

114
Bindings/python/library.py Normal file
View File

@@ -0,0 +1,114 @@
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: str
EscapeImplementation: str
ProxyServer: str
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
# python function to pass-through custom
# information to interpret which can be
# interpreted as a DSL.
def AddCustomInformation(message="") -> bool:
message = go_string(c_char_p(message.encode('utf-8')), len(message))
p2prc.CustomInformation.restype = c_char_p
status = p2prc.CustomInformation(message)
if str(status).strip("b'") == "Success":
return True
return False

View File

@@ -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

View File

@@ -0,0 +1,4 @@
dacite
schedule
sqlalchemy
requests

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

@@ -0,0 +1,11 @@
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")

View File

@@ -641,7 +641,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

View File

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

View File

@@ -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/"

View File

@@ -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"