wg-ops/wgop_common.py

176 lines
5.2 KiB
Python

# -*- coding: utf-8 -*-
import logging
import json
import traceback
import base64
import hashlib
import random
import string
# Constants
WGOP_USPEEDER_S_PBEGIN = 27100
WGOP_USPEEDER_C_PBEGIN = 28100
WGOP_LB_PBEGIN = 29000
WGOP_UC_PBEGIN = 29100
class SimpleLogger(object):
def __init__(self, name=None, filename=None, fileonly=False,
level=logging.INFO,
default_encoding='utf-8',
log_format="%(asctime)s @%(module)s [%(levelname)s] %(funcName)s: %(message)s"):
if name is None:
name = __name__
if not filename and fileonly:
raise Exception("FileOnly=True but no filename provided.")
self.logger = logging.getLogger(name)
if not getattr(self.logger, "_is_configured", None):
formatter = logging.Formatter(log_format)
if not fileonly:
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
self.logger.addHandler(console_handler)
if filename is not None:
file_handler = logging.FileHandler(filename, encoding=default_encoding)
file_handler.setFormatter(formatter)
self.logger.addHandler(file_handler)
self.logger.setLevel(level)
setattr(self.logger, "_is_configured", True)
# Just acts as a logger
def __getattr__(self, name):
return getattr(self.logger, name)
logger = SimpleLogger()
def load_config(filename=None):
config_filename = filename or "local/config.json"
try:
with open(config_filename) as f:
return json.loads(f.read())
except Exception:
logger.error("Unable to load config: {}".format(traceback.format_exc()))
return {}
def save_config(config, filename=None):
config_filename = filename or "local/config.json"
content = json.dumps(config, ensure_ascii=False, default=str, indent=2)
try:
with open(config_filename, "w", encoding='utf-8') as f:
f.write(content)
except Exception:
logger.error("Unable to save config: {}".format(traceback.format_exc()))
logger.info("Config:\n{}".format(content))
def json_to_base64(content):
return base64.b64encode(json.dumps(content, ensure_ascii=False).encode('utf-8')).decode('utf-8')
def base64_to_json(content):
return json.loads(base64.b64decode(content).decode('utf-8'))
def get_sha256(content):
return hashlib.sha256(content.encode('utf-8')).hexdigest()
def get_randpass(length):
return ''.join(random.choices(string.ascii_uppercase, k=2) + random.choices(string.ascii_lowercase + string.ascii_uppercase + string.digits, k=length - 2))
def get_quick_config(config, server_public_ip):
if config["ip"].endswith(".1"):
suggest_allowed = "{}.0/24".format('.'.join(config["ip"].split('.')[:-1]))
else:
suggest_allowed = config["ip"]
quicks = []
for server_info in config["udp2raw"]["server"]:
speeder_info = server_info["speeder"]
quick_config = {
"pubkey": config["pubkey"],
"allowed": suggest_allowed,
"remote": "{}:{}".format(server_public_ip, server_info["port"]),
"password": server_info["password"],
"ratio": speeder_info["ratio"] if speeder_info else None
}
quicks.append({
"port": server_info["port"],
"qcs": "#QCS#{}".format(json_to_base64(quick_config))
})
return quicks
class UConfigController:
next_port_speeder_server = WGOP_USPEEDER_S_PBEGIN
next_port_speeder_client = WGOP_USPEEDER_C_PBEGIN
next_port_balancer = WGOP_LB_PBEGIN
next_port_client = WGOP_UC_PBEGIN
udp2raw_config = {
"server": [],
"client": []
}
def add_server(self, port_required, password, speeder_info):
self.udp2raw_config["server"].append({
"port": port_required,
"password": get_sha256(password),
"speeder": speeder_info
})
def add_client(self, remote, password, port, speeder_info, demuxer_info, no_hash=False):
if port is None:
port = self.next_port_client
if demuxer_info:
self.next_port_client += demuxer_info["size"]
else:
self.next_port_client += 1
self.udp2raw_config["client"].append({
"remote": remote,
"password": password if no_hash else get_sha256(password),
"port": port,
"speeder": speeder_info,
"demuxer": demuxer_info
})
def new_server_speeder(self, port, ratio):
if port is None:
port = self.next_port_speeder_server
self.next_port_speeder_server += 1
return {
"port": port,
"ratio": ratio
}
def new_client_speeder(self, port, ratio):
if port is None:
port = self.next_port_speeder_client
self.next_port_speeder_client += 1
return {
"port": port,
"ratio": ratio
}
def new_demuxer(self, port, size):
if port is None:
port = self.next_port_balancer
self.next_port_balancer += 1
return {
"port": port,
"size": size
}