import asyncio import functools import json import os import socket import struct async def get_user_home(name:str): # Check args if not isinstance(name, str): raise TypeError("name have to be a string.") # Find home proc = await asyncio.create_subprocess_exec(b"getent", b"passwd", name.encode(), stdout=asyncio.subprocess.PIPE) proc_data = await proc.communicate() if not isinstance(proc_data, tuple): raise RuntimeError("Internal value isn't the expected type.") if proc.returncode != 0: raise RuntimeError("getent didn't work.") return proc_data[0].decode().split(":")[6] async def run_access_socket(path:str, async_callback, fork:bool): async def run_func(read, write): # Get user id sock = write.get_extra_info("socket") tmp = sock.getsockopt(socket.SOL_SOCKET, socket.SO_PEERCRED, struct.calcsize('3i')) tmp = struct.unpack('3i', tmp)[1] uid = str(tmp) # Run callback await async_callback(read, write, uid) server = await asyncio.start_unix_server(run_func, path=path) os.chmod(path, 0o666) if fork: if os.fork() != 0: exit(0) await server.serve_forever() _format_length = struct.Struct(">I") def rpc_callback(async_func): @functools.wraps(async_func) async def wrap_func(read, write, uid): while not read.at_eof(): # Read data try: size = _format_length.unpack(await read.readexactly(_format_length.size)) except asyncio.exceptions.IncompleteReadError: return # Client closed normaly data = json.loads((await read.readexactly(size)).decode("UTF-8")) # Callback and return result result = json.dumps(await async_func(data, uid)).encode("UTF-8") write.write(_format_length.pack(len(result))) write.write(result) await write.drain() return wrap_func class Connection(): __read = None __write = None __lock = asyncio.Lock() async def init(self, sys_socket): self.__read, self.__write = await asyncio.open_unix_connection(path=sys_socket) async def call(self, data:dict): # Check data and state if self.__read is None or self.__write is None: raise RuntimeError("Connection isn't inited.") if not isinstance(data, dict): raise TypeError("data have to be a dict") # Wait for access async with self.__lock: # Send data data = json.dumps(data).encode("UTF-8") self.__write.write(_format_length.pack(len(data))) self.__write.write(data) await self.__write.drain() # Recive date and return size = _format_length.unpack(await self.__read.readexactly(_format_length.size)) return json.loads((await self.__read.readexactly(size)).decode("UTF-8"))