pip initial changes
This commit is contained in:
269
python/p2prc-homeserver/p2prc_homeserver/__init__.py
Normal file
269
python/p2prc-homeserver/p2prc_homeserver/__init__.py
Normal file
@@ -0,0 +1,269 @@
|
||||
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
|
||||
from pathlib import Path
|
||||
import platform
|
||||
|
||||
# # 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.
|
||||
|
||||
print(platform.system().lower() + "-" + platform.machine().lower())
|
||||
|
||||
match platform.system().lower() + "-" + platform.machine().lower():
|
||||
case "darwin-arm64":
|
||||
lib_path = Path(__file__).parent.parent / "lib" / "darwin-arm64" / "p2prc.so"
|
||||
|
||||
print(str(lib_path))
|
||||
p2prc = ctypes.CDLL(str(lib_path))
|
||||
|
||||
p2prc.Init("")
|
||||
|
||||
print("main called")
|
||||
|
||||
# Start running schedule
|
||||
schedule.run_pending()
|
||||
|
||||
# Run the track processes every 3 seconds
|
||||
# schedule.every(3).seconds.do(BackgroundTrackProcess)
|
||||
|
||||
Background_track_thread = threading.Thread(target=BackgroundTrackProcess, name="Track Process")
|
||||
# Kills the tread of system exit
|
||||
Background_track_thread.setDaemon(True)
|
||||
Background_track_thread.start()
|
||||
|
||||
|
||||
# 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()
|
||||
# for _ in iter(int, 1):
|
||||
# pass
|
||||
|
||||
# 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)]
|
||||
|
||||
# Local port intended to ensure that
|
||||
def P2PRCMapPort(port="",domainname="",serveraddress=""):
|
||||
# Local Port intended to be escaped outside NAT
|
||||
# Converting to the appropirate datatype to be
|
||||
# passed as a string to GoLang.
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
# -----------------------------------------------------------------------------------
|
||||
# ----------------------------- End of helper functions -----------------------------
|
||||
# -----------------------------------------------------------------------------------
|
||||
|
||||
def infinity():
|
||||
while True:
|
||||
yield
|
||||
|
||||
# Process datatype
|
||||
@dataclass
|
||||
class Process:
|
||||
ID: str
|
||||
InternalPortNo: str
|
||||
ExternalAddress: str
|
||||
NodeInfo: Node
|
||||
TaskName: str
|
||||
CommandToRunScript: str
|
||||
CommandToKillScript: str
|
||||
Status: bool
|
||||
DomainName: str
|
||||
|
||||
@dataclass
|
||||
class Processes:
|
||||
Processes: List[Process]
|
||||
|
||||
PublicProcesses: Union[Processes, None] = None
|
||||
|
||||
# Initial defined functions
|
||||
# Exposed functions
|
||||
def SpinProcess(process: Process):
|
||||
# Starts P2PRC process
|
||||
os.system(process.CommandToRunScript)
|
||||
|
||||
# concats to the public exposed IP address + The Node information exposed P2PRC
|
||||
# server port.
|
||||
ServerAddress = process.NodeInfo.IPV4 + ":" + process.NodeInfo.ServerPort
|
||||
|
||||
process.ExternalAddress = P2PRCMapPort(port=process.InternalPortNo,
|
||||
domainname=process.DomainName,
|
||||
serveraddress=ServerAddress)
|
||||
process.ID = str(uuid.uuid4())
|
||||
process.Status = True
|
||||
|
||||
# Save the process to memory
|
||||
AddProcessToMemory(process)
|
||||
|
||||
# Save to disk
|
||||
SaveProcess()
|
||||
|
||||
return process
|
||||
|
||||
# Kill process based on the process provided
|
||||
def KillProcess(process: Process):
|
||||
os.system(process.CommandToKillScript)
|
||||
process.Status = False
|
||||
|
||||
# Remove the process from memory
|
||||
PublicProcesses.Processes.remove(process)
|
||||
|
||||
# Remove from disk
|
||||
SaveProcess()
|
||||
|
||||
return process
|
||||
|
||||
# Saves the list of processes provided as a JSON file
|
||||
def SaveProcess():
|
||||
global PublicProcesses
|
||||
with open('data.json', 'w+') as f:
|
||||
json.dump(dataclasses.asdict(PublicProcesses), f, indent=4)
|
||||
|
||||
# Read saves processes
|
||||
def ReadSavedProcesses():
|
||||
try:
|
||||
global PublicProcesses
|
||||
with open('data.json', 'r') as file:
|
||||
data = json.load(file)
|
||||
PublicProcesses = dacite.from_dict(Processes,data)
|
||||
except Exception as e:
|
||||
PublicProcesses = None
|
||||
|
||||
# Gets called when the python file is called
|
||||
ReadSavedProcesses()
|
||||
|
||||
# List processes
|
||||
def ListProcess():
|
||||
global PublicProcesses
|
||||
return PublicProcesses
|
||||
|
||||
# Adds the process dataclass the to
|
||||
# the global variable PublicProcess.
|
||||
def AddProcessToMemory(process: Process):
|
||||
global PublicProcesses
|
||||
if PublicProcesses == None:
|
||||
PublicProcesses = Processes(Processes=[process])
|
||||
# PublicProcesses.Processes.append(process)
|
||||
else:
|
||||
PublicProcesses.Processes.append(process)
|
||||
|
||||
# Tracks processes in the background and removes them
|
||||
# if not able to ping to the process
|
||||
def BackgroundTrackProcess():
|
||||
global PublicProcesses
|
||||
while 1:
|
||||
print("starting background process")
|
||||
for i in PublicProcesses.Processes:
|
||||
if not check_ping(i.ExternalAddress):
|
||||
i.Status = False
|
||||
SaveProcess()
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
def check_ping(host):
|
||||
try:
|
||||
page = requests.get('http://' + host)
|
||||
if page.status_code == 200:
|
||||
return True
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
|
||||
|
||||
# source: https://stackoverflow.com/questions/26468640/python-function-to-test-ping
|
||||
# def check_ping(host: str):
|
||||
# response = os.system("ping -c 1 " + host)
|
||||
# if response == 0:
|
||||
# pingstatus = True
|
||||
# else:
|
||||
# pingstatus = False
|
||||
# return pingstatus
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# def ProcessInformation():
|
||||
|
||||
# def ListProcess():
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user