From d64b6d8d071e9ed57666d1caf388e7b96087aade Mon Sep 17 00:00:00 2001 From: dnomd343 Date: Thu, 7 Jul 2022 00:13:53 +0800 Subject: [PATCH] feat: new Builder module --- Basis/Logger.py | 4 +-- Basis/Process.py | 7 ++--- Builder/__init__.py | 76 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 Builder/__init__.py diff --git a/Basis/Logger.py b/Basis/Logger.py index 764bf9e..383cee2 100644 --- a/Basis/Logger.py +++ b/Basis/Logger.py @@ -6,8 +6,8 @@ import logging from colorlog import ColoredFormatter logFile = 'runtime.log' -# logLevel = logging.DEBUG -logLevel = logging.WARNING +logLevel = logging.DEBUG +# logLevel = logging.WARNING dateFormat = '%Y-%m-%d %H:%M:%S' logFormat = '[%(asctime)s] [%(levelname)s] %(message)s (%(module)s.%(funcName)s)' logging.basicConfig( diff --git a/Basis/Process.py b/Basis/Process.py index a28a665..45339f1 100644 --- a/Basis/Process.py +++ b/Basis/Process.py @@ -44,7 +44,9 @@ class Process(object): workDir: A directory for storing log files and configuration files. - taskId: Task id, defaults to 12 random characters length. + taskId: Task ID, defaults to 12 random characters length. + + isStart: Start the process after class init complete. Attributes: id, workDir, output @@ -56,9 +58,6 @@ class Process(object): @staticmethod def __preExec() -> None: - # TODO: remember to remove test code - print('WARNING: pre exec at static method') - print('libc.so: ' + str(libcPath)) ctypes.CDLL(libcPath).prctl(1, signal.SIGTERM) # sub process killed when father process exit os.setpgrp() # new process group diff --git a/Builder/__init__.py b/Builder/__init__.py new file mode 100644 index 0000000..c5f80e4 --- /dev/null +++ b/Builder/__init__.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os +import copy + +from Builder import Shadowsocks + +from Basis.Logger import logging +from Basis.Process import Process +from Basis.Functions import genFlag, getAvailablePort + +default = { + 'workDir': '/tmp/ProxyC', + 'bindAddr': '127.0.0.1', + 'binDir': '/usr/bin', +} + + +class Builder(object): + """ Build the proxy client process and expose socks5 port. + + Arguments: + proxy: Proxy node information. + + bind: Socks5 proxy bind address. + + workDir: A directory for storing configuration files. + + taskId: Task ID, defaults to 12 random characters length. + + isStart: Start the process after class init complete. + + Attributes: + id, proxyType, proxyInfo, socksAddr, socksPort, output + """ + output = None + + def __loadClient(self, isStart: bool): + loadFunction = { + 'ss': Shadowsocks.load, + } + if self.proxyType not in loadFunction: + raise RuntimeError('Unknown proxy type') + logging.info('[%s] Load %s proxy client at %s -> %s' % (self.id, self.proxyType, ( + (('[%s]' if ':' in self.socksAddr else '%s') + ':%i') % (self.socksAddr, self.socksPort) + ), str(self.proxyInfo))) + configFile = os.path.join(self.__workDir, self.id + '.json') + command, fileContent, envVar = loadFunction[self.proxyType](self.proxyInfo, { + 'addr': self.socksAddr, + 'port': self.socksPort, + }, configFile) + envVar['PATH'] = default['binDir'] + fileObject = { + 'path': configFile, + 'content': fileContent + } + self.__process = Process(self.__workDir, taskId = self.id, + isStart = isStart, cmd = command, env = envVar, file = fileObject) + + def __init__(self, proxy: dict, taskId: str = '', isStart: bool = True, + bind: str = default['bindAddr'], workDir: str = default['workDir']) -> None: + self.id = genFlag(length = 12) if taskId == '' else taskId + self.__workDir = workDir + self.proxyType = proxy['type'] + self.proxyInfo = copy.copy(proxy['info']) + self.socksAddr = bind + self.socksPort = getAvailablePort() + self.__loadClient(isStart) + + def status(self) -> bool: + return self.__process.status() + + def destroy(self) -> None: + self.__process.quit() + self.output = self.__process.output