From 13dc23c5d8ffc666b49138ac38262d90b5f1060d Mon Sep 17 00:00:00 2001 From: SantaSpeen Date: Sat, 15 Mar 2025 02:45:08 +0300 Subject: [PATCH] Move NamesPipe to connectors/named_pipe --- .../connectors/named_pipe/WinConnectClient.py | 40 +++++++++++++++++++ .../connectors/named_pipe/WinConnectServer.py | 38 ++++++++++++++++++ .../named_pipe/_WinConnectNamedPipe.py | 36 +++++++++++++++++ winConnect/connectors/named_pipe/__init__.py | 2 + 4 files changed, 116 insertions(+) create mode 100644 winConnect/connectors/named_pipe/WinConnectClient.py create mode 100644 winConnect/connectors/named_pipe/WinConnectServer.py create mode 100644 winConnect/connectors/named_pipe/_WinConnectNamedPipe.py create mode 100644 winConnect/connectors/named_pipe/__init__.py diff --git a/winConnect/connectors/named_pipe/WinConnectClient.py b/winConnect/connectors/named_pipe/WinConnectClient.py new file mode 100644 index 0000000..ba7f39f --- /dev/null +++ b/winConnect/connectors/named_pipe/WinConnectClient.py @@ -0,0 +1,40 @@ +import pywintypes +import win32file + +from winConnect.exceptions import WinConnectConnectionNoPipeException +from ._WinConnectNamedPipe import WinConnectNamedPipe +from ..WinConnectClient import WinConnectClient + + +class WinConnectPipeClient(WinConnectNamedPipe, WinConnectClient): + # see: https://mhammond.github.io/pywin32/win32pipe__CreateNamedPipe_meth.html + pipe_desiredAccess = win32file.GENERIC_READ | win32file.GENERIC_WRITE # Access mode (read/write) + pipe_shareMode = 0 # Share mode (None) + pipe_sa = None # Security attributes + pipe_CreationDisposition = win32file.OPEN_EXISTING # Open mode (open existing) + pipe_flagsAndAttributes = 0 # Flags and attributes + pipe_hTemplateFile = None # Template file + + def __init__(self, pipe_name: str): + super().__init__(pipe_name) + + def _open_pipe(self): + try: + self._pipe = win32file.CreateFile( + self._pipe_name, + self.pipe_desiredAccess, + self.pipe_shareMode, + self.pipe_sa, + self.pipe_CreationDisposition, + self.pipe_flagsAndAttributes, + self.pipe_hTemplateFile + ) + self._opened = True + self._connected = True + self._log.debug(f"[{self._pipe_name}] Pipe opened") + except pywintypes.error as e: + if e.winerror == 2: + exc = WinConnectConnectionNoPipeException(f"Error while opening pipe: Pipe not found") + exc.real_exc = e + raise exc + raise e diff --git a/winConnect/connectors/named_pipe/WinConnectServer.py b/winConnect/connectors/named_pipe/WinConnectServer.py new file mode 100644 index 0000000..17ab0fd --- /dev/null +++ b/winConnect/connectors/named_pipe/WinConnectServer.py @@ -0,0 +1,38 @@ +import win32pipe + +from ._WinConnectNamedPipe import WinConnectNamedPipe +from ..WinConnectServer import WinConnectServer + + +class WinConnectPipeServer(WinConnectNamedPipe, WinConnectServer): + # see: https://mhammond.github.io/pywin32/win32pipe__CreateNamedPipe_meth.html + pipe_openMode = win32pipe.PIPE_ACCESS_DUPLEX # Open mode (read/write) + pipe_pipeMode = win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT # Pipe mode (message type, message read mode, blocking mode) + pipe_nMaxInstances = 1 # Max number of instances + pipe_nDefaultTimeOut = 0 # ~ ms + pipe_sa = None # Security attributes + + def __init__(self, pipe_name: str): + super().__init__(pipe_name) + self.run = True + + def _open_pipe(self): + pipe_nOutBufferSize, pipe_nInBufferSize = self._body_max_size+20, self._body_max_size+20 + self._log.debug(f"[{self._pipe_name}] Creating pipe. " + f"Settings: {self.pipe_openMode=}, {self.pipe_pipeMode=}, {self.pipe_nMaxInstances=}, " + f"{pipe_nOutBufferSize=}, {pipe_nInBufferSize=}, {self.pipe_nDefaultTimeOut=}, {self.pipe_sa=}") + self._pipe = win32pipe.CreateNamedPipe( + self._pipe_name, + self.pipe_openMode, + self.pipe_pipeMode, + self.pipe_nMaxInstances, + pipe_nOutBufferSize, + pipe_nInBufferSize, + self.pipe_nDefaultTimeOut, + self.pipe_sa + ) + self._opened = True + self._log.debug(f"[{self._pipe_name}] Pipe opened") + + def _wait_connect(self): + win32pipe.ConnectNamedPipe(self._pipe, None) diff --git a/winConnect/connectors/named_pipe/_WinConnectNamedPipe.py b/winConnect/connectors/named_pipe/_WinConnectNamedPipe.py new file mode 100644 index 0000000..5a6c821 --- /dev/null +++ b/winConnect/connectors/named_pipe/_WinConnectNamedPipe.py @@ -0,0 +1,36 @@ +import logging + +import pywintypes +import win32file + +from winConnect import exceptions +from winConnect.connectors.WinConnectBase import WinConnectBase + + +class WinConnectNamedPipe(WinConnectBase): + def __init__(self, pipe_name: str): + super().__init__(pipe_name) + self._log = logging.getLogger(f"WinConnectNamedPipe:{pipe_name}") + self._pipe_name = r'\\.\pipe\{}'.format(pipe_name) + self._pipe = None + + def __raw_read(self, size): + with self._pipe_lock: + try: + _, data = win32file.ReadFile(self._pipe, size) + return data + except pywintypes.error as e: + if e.winerror == 109: + exc = exceptions.WinConnectConnectionClosedException("Connection closed") + exc.real_exc = e + raise exc + raise e + + def __raw_write(self, packet): + with self._pipe_lock: + if self.closed: + raise exceptions.WinConnectSessionClosedException("Session is closed") + win32file.WriteFile(self._pipe, packet) + + def _close_pipe(self): + win32file.CloseHandle(self._pipe) diff --git a/winConnect/connectors/named_pipe/__init__.py b/winConnect/connectors/named_pipe/__init__.py new file mode 100644 index 0000000..6dbbfcc --- /dev/null +++ b/winConnect/connectors/named_pipe/__init__.py @@ -0,0 +1,2 @@ +from .WinConnectClient import WinConnectPipeClient +from .WinConnectServer import WinConnectPipeServer